11

当使用 Google Reader 并在“扩展”视图中浏览 RSS 条目时,一旦在屏幕上显示了一定百分比的 div,条目将自动标记为“已读”(在谷歌读者)。因此,当我逐行向下滚动时,javascript 代码可以确定 a) 条目正在可见窗口中呈现 b) 一定数量是可见的,当满足这些条件时,状态切换为读取.

有谁知道该功能是如何实现的?具体来说,这里有没有人知道如何判断一个 div 是否已经滚动到视图中,以及有多少 div 是可见的?

顺便说一句,我正在使用 jQuery,所以如果有人有任何 jQuery 特定的示例,他们将不胜感激。

4

6 回答 6

4

真正的诀窍是跟踪滚动条在包含您的项目的元素中的位置。这是我曾经编写的一些代码:http: //pastebin.com/f4a329cd9

您可以看到,当您滚动它时,它会改变焦点。您只需要向处理每个焦点更改的函数添加更多处理程序代码。它可以双向滚动,也可以通过在滚动条上单击鼠标右键,简单的鼠标跟踪不会给你(尽管在这种情况下,因为示例元素都是相同的大小,具有相同的文本,很难说它确实滚动了)。另一个问题是当容器触底时该怎么办。我现在的解决方案只适用于FF。如果你想让它在 IE 中看起来不错,你将不得不使用一个与背景融为一体的虚拟元素,就像我在代码中注释掉的那个一样。

于 2008-12-15T04:51:44.450 回答
2

我刚遇到这个,因为我需要同样的东西,它看起来非常有用:

http://www.appelsiini.net/projects/viewport

于 2008-12-28T06:53:12.633 回答
0

根据我的经验,只有当我将鼠标悬停或单击时,Reader 才会将某些内容标记为已读。假设当您滚动时,您的鼠标位于 div 上(滚动时我倾向于将鼠标放在屏幕的右边缘),这可能解释了它仅在显示某个百分比时才被标记的外观。

不过,我可能(而且很可能)错了。我只知道在阅读器中滚动浏览我的项目的行为并没有标记它们。我必须确保鼠标在滚动时鼠标悬停在它们上方。

于 2008-12-09T20:43:11.613 回答
0

dom 和 javascript 可让您计算元素与其父元素的偏移量。要计算与窗口的偏移量,您需要使用递归并爬到顶部窗口,并将其与窗口的大小进行比较。由于跨浏览器问题和 iframe,它变得更加复杂。

据我所知,原型提供了一种简单的viewportOffset方法,可以为您完成大部分工作。您还可以检查 和 的getOffsetParent来源scrollTo。我不了解 jquery,但我希望它能够提供类似的方法。

我的猜测是谷歌阅读器中的脚本只是超时运行,可能每秒几次,或者可能是响应滚动事件。在这两种情况下,我确信它是自适应的(超时根据用户滚动的速度等而变化),并且它足够聪明,不会成为资源占用(即,不要只检查所有 div文件)

于 2008-12-13T23:36:03.107 回答
0

为了计算一个元素是否可见,你可以创建这样一个函数(信用在这里https://stackoverflow.com/a/22480938/825240):

function isScrolledIntoView(element) {
  var elementTop = element.getBoundingRect().top;
  var elementBottom = element.getBoundingRect().bottom;

  var isVisible = (elementTop <= window.innerHeight) && (elementBottom >= 0);
  return isVisible;
}

您可以通过计算是否已读取元素来根据您的情况自定义该函数:

function isRead(element) {
  var elementTop = element.getBoundingRect().top;
  var elementBottom = element.getBoundingRect().bottom;
  var elementHeight = elementBottom - elementTop;

  // if 75% of the document has been scrolled, we'll assume it's been read
  var readIfPercentage = 0.75;

  // an element has been read if the top has been scrolled up out of view
  // and at least 75% of the element is no longer visible
  var isRead = (elementTop < 0 && Math.abs(elementTop) / elementHeight >= readIfPercentage);
  return isRead;
}

然后你可以调用上面的函数,传入一个 DOM 节点作为元素:

isScrolledIntoView(document.getElementById('targetDiv');
//or
isRead(document.getElementById('targetDiv');

您可以通过创建滚动侦听器将它们联系在一起(jQuery 使这非常容易):

function setScrollListener() {

  var scrollEventHandler = function() {
    if (isRead(document.getElementById('article'))) {
      // set article to 'read'
    }
  }

  // on scroll, fire the event handler
  $(document).scroll(scrollEventHandler);
}

值得注意的是,如果你想解绑滚动监听,比如文章都读完了,不再需要监听滚动,可以在scrollEventHandler中调用解绑函数。它很简单:

function unbindScrollEventHandler() {
  $(document).unbind('scroll', scrollEventHandler);
}
于 2017-10-03T13:20:08.157 回答
0

你可以试试这个,关键是元素必须对内部身体更多可见并满足可见比例(在本例中为0.85)。

isRead(element) {
   let rect = element.getBoundingClientRect();
   const visibleRatio = 0.85;
   let elementRatio = (window.innerHeight - Math.abs(rect.top))/rect.height;
   let isRead = (rect.top >= 0) && (elementRatio >= visibleRatio);
   return isRead; 
}
于 2018-05-28T19:11:58.047 回答