How to Check if element is visible after scrolling?
我正在通过Ajax加载元素。只有向下滚动页面时,其中一些才可见。我有没有办法知道元素现在是否在页面的可见部分?
- 我不太明白这个问题。你能试着添加更多的信息吗?
- 他意味着他希望一个方法知道给定的元素是否显示在浏览器窗口中,或者用户是否需要滚动查看它。
- 要检查元素在容器中是否完全可见,只需添加一个额外的选择器参数,并为其重新使用elem代码。
Library.IsElementVisibleInContainer = function (elementSelector, containerSelector) { var containerViewTop = $(containerSelector).offset().top; var containerViewBottom = containerViewTop + $(containerSelector).height(); 。 - 这个"图书馆"是什么?@lindsay?
- 如何判断一个dom元素在当前视区中是否可见的可能副本?
- 这个库只是我创建的一个函数。如
function Library() { } 。我这样写我的javascript是因为我发现它更容易阅读/维护,而不是仅仅拥有一个函数(例如,isElementVisibleInContainer),并且不知道它来自哪里。 - 交叉口观察员将是答案…但现在还不是很好,除非你用一个多填充的Safari和IE.Observer是一个新版本的事件。当元素的nn%可见时,这将触发回调。请参见developer.mozilla.org/en-us/docs/web/api/…
- 如何判断一个dom元素在当前视区中是否可见的可能副本?
- 所有的答案都会触发回流,所以它可能是瓶颈,如果支持的话,请使用intersectionobserver。它将在现代浏览器上具有更好的性能,
这应该可以做到:
1 2 3 4 5 6 7 8 9 10 | function isScrolledIntoView(elem) { var docViewTop = $(window).scrollTop(); var docViewBottom = docViewTop + $(window).height(); var elemTop = $(elem).offset().top; var elemBottom = elemTop + $(elem).height(); return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); } |
简单效用函数这将允许您调用一个实用程序函数,该函数接受您要查找的元素,如果您希望元素完全在视图中或部分在视图中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | function Utils() { } Utils.prototype = { constructor: Utils, isElementInView: function (element, fullyInView) { var pageTop = $(window).scrollTop(); var pageBottom = pageTop + $(window).height(); var elementTop = $(element).offset().top; var elementBottom = elementTop + $(element).height(); if (fullyInView === true) { return ((pageTop < elementTop) && (pageBottom > elementBottom)); } else { return ((elementTop <= pageBottom) && (elementBottom >= pageTop)); } } }; var Utils = new Utils(); |
。
用法
1 2 3 4 5 6 7 | var isElementInView = Utils.isElementInView($('#flyout-left-container'), false); if (isElementInView) { console.log('in view'); } else { console.log('out of view'); } |
- 请注意,只有当文档是滚动的元素时,这才有效,也就是说,您没有检查滚动内部窗格中某个元素的可见性。
- 如何添加一点偏移量?
- 只在我用
window.innerHeight 的时候工作 - 对于
elemTop ,我使用$(elem).position().top ,对于elemBottom ,我使用elemTop + $(elem).outerHeight(true) 。 - 另外,如果整个元素都在视图中,则使用
&& 测试。如果您想知道元素的任何部分是否在视图中,请使用|| 。 - 在香草中添加了相同的方法:stackoverflow.com/a/22480938/643514
- 谢谢你的加入,@sarahvessels!这对我很有用。
- 截至2014年6月6日,我无法让它在火狐29上正常工作。"$(elem).offset().top"将始终返回静态结果,即使在滚动之后也是如此。我最终找到了一个使用普通javascript方法getboundingclientrect()的解决方案。
- 对于:"视图中元素的任何部分",我使用:(((elemtop>=docviewtop)&;&;(elemtop<=docviewbottom))((elembottom>=docviewtop)&;&;(elembottom<=docviewbottom)))
- 我发现结合两种选择最有效——
return ((elemBottom >= docViewBottom) && (elemTop <= docViewTop)) || ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); 。 - 对于"视图中的元素的任何部分",
((elemTop <= docViewBottom) && (elemBottom >= docViewTop)) 完全覆盖了所有情况——即使顶部和底部边缘在屏幕外,并且只有中间部分在视图中。 - 对于"视图中元素的任何部分"
Math.min(elemBottom, docViewBottom) >= Math.max(elemeTop, docViewTop); 。 - @这个答案是jquery。
- 此代码有效!甚至可以用jquery用户界面中的
$(element).scrollParent() 替换$(window) ,这也适用于可滚动元素(即overflow-y:scroll)。 - 当我将event.target视为$(window)时,这不起作用。我有
>
- 在所有情况下,它似乎都不起作用。例如,即使在我滚动到窗口的最底部之后,我还是得到了:
docViewTop: 496, docViewBottom: 1039, elemTop: 1029.3125, elemBottom: 1039.3125 ,函数返回false (=它不可见)。- 这不适用于浮动元素。它没有考虑元素的绝对位置,并且错误地认为它在屏幕外滚动。
这个答案是香草味的:
1
2
3
4
5
6
7
8
9
10
11function isScrolledIntoView(el) {
var rect = el.getBoundingClientRect();
var elemTop = rect.top;
var elemBottom = rect.bottom;
// Only completely visible elements return true:
var isVisible = (elemTop >= 0) && (elemBottom <= window.innerHeight);
// Partially visible elements return true:
//isVisible = elemTop < window.innerHeight && elemBottom >= 0;
return isVisible;
}号
- 难道这不是
isVisible = elementTop < window.innerHeight && elementBottom >= 0 吗?否则,屏幕上的半个元素返回false。 - 不。我检查一些元素是否在页面上完全可见。如果您想检查某个部分的可见性,可以自定义此代码段。
- 我发现这个答案比选择的答案表现更好。更简单。
- element.getboundingclientrect bottom和top给了我正确的想法。+ 1
- 与已批准的答案相比,这对数百个元素的waaaay性能要好得多。
- 有没有什么特别的原因jquery比普通的更受欢迎?
- @gCampbell是的,人们害怕使用DOM,或者不知道API,或者干脆忘记它的存在。尽管在许多情况下不再需要jquery,但不幸的是它已成为事实上的标准。公平地说,和大多数Web技术一样,使用DOM根本不好玩。
- @MarcDiethelm,尤其是名称空间,例如SVG。
- 如果元素可见但比滚动区域宽,则函数将始终返回false。
- @当然,因为这里可见意味着可见,而不是部分可见;)
- 我将
el.getBoundingClientRect() 的结果缓存在一个变量中,而不是两次调用它来挤出一些免费的性能提升。 - 在这里看到一个小小提琴示范-jsfiddle.net/shaaraddalvi/4rp09jl0
getBoundingClientRect() 引起"布局震荡"。有没有建议如何在这方面进行滚动?- 这在iPhone上有效吗?
到目前为止,我找到的最好的方法是jquery显示插件。很有魅力。
Mimics a custom"appear" event, which fires when an element scrolls into view or otherwise becomes visible to the user.
1
2
3$('#foo').appear(function() {
$(this).text('Hello world');
});This plugin can be used to prevent unnecessary requests for content that's hidden or outside the viewable area.
号
- 毫无疑问,这是一个很酷的插件,但没有回答问题。
- 虽然jquery-appear插件对主页面上的内容很好,但不幸的是它有固定大小的滚动分区溢出的问题。当绑定元素在页面的可查看区域内但在DIV的可查看区域外时,事件可能会提前触发,然后当元素在DIV中进入视图时,事件可能不会按预期触发。
- 有消失的插件吗?
- @Shamoon检查
appear plugin 的源代码,您可能只需要在某个地方添加一个! 来获取disappear 插件。 - 检查这里的Appear插件的演示morr.github.io/appear.html,它还有一个消失的功能。
- 注意,这不适用于jquery 1.11.x github.com/morr/jquery.appear/issues/37
- @shamoon:$('somesselector').on('消失',函数(事件,$all_消失//此元素现在在浏览器视区)之外;
这是我的纯javascript解决方案,如果它也隐藏在可滚动容器中,它也可以工作。
这里演示(也尝试调整窗口大小)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16var visibleY = function(el){
var rect = el.getBoundingClientRect(), top = rect.top, height = rect.height,
el = el.parentNode
// Check if bottom of the element is off the page
if (rect.bottom < 0) return false
// Check its within the document viewport
if (top > document.documentElement.clientHeight) return false
do {
rect = el.getBoundingClientRect()
if (top <= rect.bottom === false) return false
// Check if the element is out of view due to a container scrolling
if ((top + height) <= rect.top) return false
el = el.parentNode
} while (el != document.body)
return true
};号
编辑2016-03-26:我已经更新了解决方案,考虑到滚动超过元素,所以它隐藏在可滚动容器的顶部。编辑2018-10-08:当滚动到屏幕上方的视图之外时更新为处理。
- 谢谢,也许最好是
return top <= document.documentElement.clientHeight && top >= 0; 。 - +1这是唯一一个考虑到元素递归性质的编码(即不是第三方)答案。我已经扩展到处理水平、垂直和页面滚动:jsfiddle.net/9nuqpgqa
- 此解决方案只检查元素的顶部。如果第一个顶部像素可见,即使项目的其余部分不可见,它也将返回true。要检查整个元素是否可见,还需要检查Bottom属性。
- 是的,干净!用于帮助编写此答案(其中credit为js comment)。
- 缺少;在循环中的第二个"return false"之后
- 不幸的是,它不起作用:jsfiddle.net/vanowm/hmmv4glr/24
- 在该代码中,当元素可见时,我必须将我的函数放在我想调用的地方?
- 有些边缘情况下,此解决方案不起作用。
jquery waypoints插件在这里非常不错。
1
2
3$('.entry').waypoint(function() {
alert('You have scrolled to an entry.');
});。
在插件的站点上有一些例子。
- 对我来说,它只适用于偏移的
$('#my-div').waypoint(function() { console.log('Hello there!'); }, { offset: '100%' }); 。
怎么样
1
2
3function isInView(elem){
return $(elem).offset().top - $(window).scrollTop() < $(elem).height() ;
}号
之后,一旦元素出现在这样的视图中,您就可以触发您想要的任何东西。
1
2
3
4
5$(window).scroll(function(){
if (isInView($('.classOfDivToCheck')))
//fire whatever you what
dothis();
})号
对我来说很好
- 这对我很有用,但我在stackoverflow.com/questions/487073/&hellip;:)上使用了看起来更完整的函数isscrolledintoview。
- 我认为应该是$(window).scrolltop()<$(elem).offset().top+$(elem).height();
- 我的修改如下:`返回$(window).scrolltop()+$(window).height()>$(elem).offset().top+$(elem).height();。`
使用("new")IntersectionObserver API确定元素是否在视区中可见是非常简单和有效的。通过使用观察器,它消除了附加
scroll 事件和手动检查事件回调的需要。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28// this is the target which is observed
var target = document.querySelector('div');
// configure the intersection observer instance
var intersectionObserverOptions = {
root: null,
rootMargin: '150px',
threshold: 1.0
}
var observer = new IntersectionObserver(onIntersection, intersectionObserverOptions);
// provice the observer with a target
observer.observe(target);
function onIntersection(entries){
entries.forEach(entry => {
console.clear();
console.log(entry.intersectionRatio)
target.classList.toggle('visible', entry.intersectionRatio > 0);
// Are we in viewport?
if (entry.intersectionRatio > 0) {
// Stop watching
// observer.unobserve(entry.target);
}
});
}号
1
2.box{ width:100px; height:100px; background:red; margin:1000px; }
.box.visible{ background:green; }号
1Scroll both Vertically & Horizontally...号
查看浏览器支持表(IE/Safari不支持)- 谢谢!这对我来说是可行的,而且还可以在ie11中使用github.com/w3c/intersectionobserver。
- 迄今为止最好的解决方案。在没有PolyFill的IE11工作!
- 请注意,这在iOS/MacOS Safari中仍然不受支持,很遗憾。如果您选择PolyFill,这是一大组用户,请确保检查性能问题。
- @利兰-这取决于项目。对于我的所有项目,这是一个绝对0用户组。我不建立网站,而是建立网络系统;)
- 同类产品中最好的,希望它的兼容性更高。
WebResourcesDepot在滚动时编写了一个要加载的脚本,该脚本在一段时间前使用了jQuery。你可以在这里观看他们的现场演示。他们的主要功能是:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16$(window).scroll(function(){
if ($(window).scrollTop() == $(document).height() - $(window).height()){
lastAddedLiveFunc();
}
});
function lastAddedLiveFunc() {
$('div#lastPostsLoader').html('<img src="images/bigLoader.gif">');
$.post("default.asp?action=getLastPosts&lastPostID="+$(".wrdLatest:last").attr("id"),
function(data){
if (data !="") {
$(".wrdLatest:last").after(data);
}
$('div#lastPostsLoader').empty();
});
};号
特威克·斯科特·道丁的酷功能满足了我的要求-这用于查找元素是否刚刚滚动到屏幕,即它的上边缘。
1
2
3
4
5
6
7function isScrolledIntoView(elem)
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
return ((elemTop <= docViewBottom) && (elemTop >= docViewTop));
}号
这里的大多数答案都没有考虑到一个元素也可以隐藏,因为它被滚动到一个DIV的视图之外,而不仅仅是整个页面。
为了覆盖这种可能性,您基本上必须检查元素是否位于每个父元素的边界内。
这个解决方案就是这样做的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26function(element, percentX, percentY){
var tolerance = 0.01; //needed because the rects returned by getBoundingClientRect provide the position up to 10 decimals
if(percentX == null){
percentX = 100;
}
if(percentY == null){
percentY = 100;
}
var elementRect = element.getBoundingClientRect();
var parentRects = [];
while(element.parentElement != null){
parentRects.push(element.parentElement.getBoundingClientRect());
element = element.parentElement;
}
var visibleInAllParents = parentRects.every(function(parentRect){
var visiblePixelX = Math.min(elementRect.right, parentRect.right) - Math.max(elementRect.left, parentRect.left);
var visiblePixelY = Math.min(elementRect.bottom, parentRect.bottom) - Math.max(elementRect.top, parentRect.top);
var visiblePercentageX = visiblePixelX / elementRect.width * 100;
var visiblePercentageY = visiblePixelY / elementRect.height * 100;
return visiblePercentageX + tolerance > percentX && visiblePercentageY + tolerance > percentY;
});
return visibleInAllParents;
};。
它还允许您指定它在每个方向上的可见百分比。它不包括可能由于其他因素而隐藏的可能性,如
display: hidden 。这应该适用于所有主要的浏览器,因为它只使用
getBoundingClientRect 。我在Chrome和Internet Explorer 11中亲自测试过它。- 感谢您提供此代码。我想知道,如果您有多个嵌套的可滚动元素,如何在Scroll上添加事件侦听器?似乎单独向窗口添加侦听器是不够的,我们是否必须遍历回顶部父级才能将侦听器添加到每个可滚动容器中?
- @MR1031011应该可以将处理程序添加到窗口,然后检查目标以标识滚动的容器。
- 不起作用:jsfiddle.net/vanowm/hmmv4glr/21
- 对,它不适用于@vanowm给出的示例,
IsScrolledintoView是一个非常需要的功能,所以我尝试了它,它适用于不比视区高的元素,但是如果元素比视区大,它就不工作。要解决这个问题,很容易改变条件
1return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));号
为此:
1return (docViewBottom >= elemTop && docViewTop <= elemBottom);号
参见演示:http://jsfiddle.net/rrsmq/
jquery有一个名为inview的插件,它添加了一个新的"inview"事件。
以下是不使用事件的jquery插件的一些代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18$.extend($.expr[':'],{
inView: function(a) {
var st = (document.documentElement.scrollTop || document.body.scrollTop),
ot = $(a).offset().top,
wh = (window.innerHeight && window.innerHeight < $(window).height()) ? window.innerHeight : $(window).height();
return ot > st && ($(a).height() + ot) < (st + wh);
}
});
(function( $ ) {
$.fn.inView = function() {
var st = (document.documentElement.scrollTop || document.body.scrollTop),
ot = $(this).offset().top,
wh = (window.innerHeight && window.innerHeight < $(window).height()) ? window.innerHeight : $(window).height();
return ot > st && ($(this).height() + ot) < (st + wh);
};
})( jQuery );我在一个叫james的家伙的评论(http://remysharp.com/2009/01/26/element-in-view-event-plugin/)中发现了这个。
- 遗憾的是,jquery inview不再被维护,也不适用于当前版本的jquery。
- 嗯。。。它适用于我在1.11.1,这是一个当前版本
- jquery 1是为了支持传统的浏览器,jquery 2中有新功能。
- 链接不会在页面更新时显示示例。
1
2
3
4
5
6
7
8function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop(),
docViewBottom = docViewTop + $(window).height(),
elemTop = $(elem).offset().top,
elemBottom = elemTop + $(elem).height();
//Is more than half of the element visible
return ((elemTop + ((elemBottom - elemTop)/2)) >= docViewTop && ((elemTop + ((elemBottom - elemTop)/2)) <= docViewBottom));
}。
这将考虑元素具有的任何填充、边框或边距,以及大于视区本身的元素。
1
2
3
4
5
6
7
8
9
10
11function inViewport($ele) {
var lBound = $(window).scrollTop(),
uBound = lBound + $(window).height(),
top = $ele.offset().top,
bottom = top + $ele.outerHeight(true);
return (top > lBound && top < uBound)
|| (bottom > lBound && bottom < uBound)
|| (lBound >= top && lBound <= bottom)
|| (uBound >= top && uBound <= bottom);
}号
要调用它,请使用类似这样的方法:
1
2
3
4var $myElement = $('#my-element'),
canUserSeeIt = inViewport($myElement);
console.log(canUserSeeIt); // true, if element is visible; false otherwise以下是http://web-profile.com.ua提供的另一个解决方案/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33<script type="text/javascript">
$.fn.is_on_screen = function(){
var win = $(window);
var viewport = {
top : win.scrollTop(),
left : win.scrollLeft()
};
viewport.right = viewport.left + win.width();
viewport.bottom = viewport.top + win.height();
var bounds = this.offset();
bounds.right = bounds.left + this.outerWidth();
bounds.bottom = bounds.top + this.outerHeight();
return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
};
if( $('.target').length > 0 ) { // if target element exists in DOM
if( $('.target').is_on_screen() ) { // if target element is visible on screen after DOM loaded
$('.log').html('target element is visible on screen'); // log info
} else {
$('.log').html('target element is not visible on screen'); // log info
}
}
$(window).scroll(function(){ // bind window scroll event
if( $('.target').length > 0 ) { // if target element exists in DOM
if( $('.target').is_on_screen() ) { // if target element is visible on screen after DOM loaded
$('.log').html('target element is visible on screen'); // log info
} else {
$('.log').html('target element is not visible on screen'); // log info
}
}
});号
在jsFiddle中查看
- 到目前为止对我来说最好的解决方案。工作做得很好,很简单。
- 太棒了!!!!会看到我怎么用这个,因为它比我看到的任何东西都好
我需要检查可滚动DIV容器中元素的可见性。
1
2
3
4
5
6
7
8
9
10
11
12//p = DIV container scrollable
//e = element
function visible_in_container(p, e) {
var z = p.getBoundingClientRect();
var r = e.getBoundingClientRect();
// Check style visiblilty and off-limits
return e.style.opacity > 0 && e.style.display !== 'none' &&
e.style.visibility !== 'hidden' &&
!(r.top > z.bottom || r.bottom < z.top ||
r.left > z.right || r.right < z.left);
}。
- 如果我将
e.style.opacity > 0 改为(!e.style.opacity || e.style.opacity > 0) ,这对我很有用,因为默认情况下,它是ff中的空字符串。
检查元素(
el 是否在滚动分区(holder 中可见)的普通香草色1
2
3
4
5
6
7
8
9function isElementVisible (el, holder) {
holder = holder || document.body
const { top, bottom, height } = el.getBoundingClientRect()
const holderRect = holder.getBoundingClientRect()
return top <= holderRect.top
? holderRect.top - top <= height
: bottom - holderRect.bottom <= height
},。
jquery的用法:
1
2
3var el = $('tr:last').get(0);
var holder = $('table').get(0);
isVisible = isScrolledIntoView(el, holder);您可以使用jquery插件"on screen"在滚动时检查元素是否在当前视区中。当选择器出现在屏幕上时,该插件将选择器的":on screen"设置为"真"。这是可以包含在项目中的插件的链接。"http://benickles.github.io/onscreen/jquery.onscreen.min.js"
你可以试试下面的例子,它对我很有用。
1
2
3
4
5
6
7
8
9
10$(document).scroll(function() {
if($("#div2").is(':onScreen')) {
console.log("Element appeared on Screen");
//do all your stuffs here when element is visible.
}
else {
console.log("Element not on Screen");
//do all your stuffs here when element is not visible.
}
});HTML代码:
1<hr />号
CSS:
1
2
3
4
5
6#div1 {
background-color: red;
}
#div2 {
background-color: green;
}基于这个伟大的答案,您可以使用ES2015+进一步简化它:
1
2
3
4function isScrolledIntoView(el) {
const { top, bottom } = el.getBoundingClientRect()
return top >= 0 && bottom <= window.innerHeight
}。
如果你不关心从窗口出来的顶部,只关心底部已经被看到,这可以简化为
1
2
3function isSeen(el) {
return el.getBoundingClientRect().bottom <= window.innerHeight
}甚至连一条线
1const isSeen = el => el.getBoundingClientRect().bottom <= window.innerHeight。
下面是一种使用moootools(水平、垂直或同时使用两者)实现相同功能的方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62Element.implement({
inVerticalView: function (full) {
if (typeOf(full) ==="null") {
full = true;
}
if (this.getStyle('display') === 'none') {
return false;
}
// Window Size and Scroll
var windowScroll = window.getScroll();
var windowSize = window.getSize();
// Element Size and Scroll
var elementPosition = this.getPosition();
var elementSize = this.getSize();
// Calculation Variables
var docViewTop = windowScroll.y;
var docViewBottom = docViewTop + windowSize.y;
var elemTop = elementPosition.y;
var elemBottom = elemTop + elementSize.y;
if (full) {
return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)
&& (elemBottom <= docViewBottom) && (elemTop >= docViewTop) );
} else {
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
},
inHorizontalView: function(full) {
if (typeOf(full) ==="null") {
full = true;
}
if (this.getStyle('display') === 'none') {
return false;
}
// Window Size and Scroll
var windowScroll = window.getScroll();
var windowSize = window.getSize();
// Element Size and Scroll
var elementPosition = this.getPosition();
var elementSize = this.getSize();
// Calculation Variables
var docViewLeft = windowScroll.x;
var docViewRight = docViewLeft + windowSize.x;
var elemLeft = elementPosition.x;
var elemRight = elemLeft + elementSize.x;
if (full) {
return ((elemRight >= docViewLeft) && (elemLeft <= docViewRight)
&& (elemRight <= docViewRight) && (elemLeft >= docViewLeft) );
} else {
return ((elemRight <= docViewRight) && (elemLeft >= docViewLeft));
}
},
inView: function(full) {
return this.inHorizontalView(full) && this.inVerticalView(full);
}});我的应用程序中有这样一个方法,但它不使用jquery:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25/* Get the TOP position of a given element. */
function getPositionTop(element){
var offset = 0;
while(element) {
offset += element["offsetTop"];
element = element.offsetParent;
}
return offset;
}
/* Is a given element is visible or not? */
function isElementVisible(eltId) {
var elt = document.getElementById(eltId);
if (!elt) {
// Element not found.
return false;
}
// Get the top and bottom position of the given element.
var posTop = getPositionTop(elt);
var posBottom = posTop + elt.offsetHeight;
// Get the top and bottom position of the *visible* part of the window.
var visibleTop = document.body.scrollTop;
var visibleBottom = visibleTop + document.documentElement.offsetHeight;
return ((posBottom >= visibleTop) && (posTop <= visibleBottom));
}编辑:此方法适用于(至少版本6)。阅读评论以了解与FF的兼容性。
- 出于某种原因,document.body.scrolltop始终返回0(在ff3上)。将其更改为var visibletop=(document.documentElement.scrolltop?document.documentElement&zwnj;&8203;.scrollTop:document.&zwnj;&8203;body.scrollTop);
- 对不起。我的应用程序只能在IE6中运行(是的,我并不幸运:()所以我从来没有在FF中测试过这个。
- 这是最好的答案,如果它是正确的。请纠正您的一句话:
var visibleBottom = visibleTop + window.innerHeight; ,我没有使用jquery,您帮助我找到了正确的答案。
修改了已接受的答案,以便元素必须将其显示属性设置为"无"以外的其他值,以使质量可见。
1
2
3
4
5
6
7
8
9
10function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
var elemDisplayNotNone = $(elem).css("display") !=="none";
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop) && elemDisplayNotNone);
}号
如果您想在另一个DIV中对滚动项进行调整,
1
2
3
4
5
6
7
8
9
10
11
12
13
14function isScrolledIntoView (elem, divID)
{
var docViewTop = $('#' + divID).scrollTop();
var docViewBottom = docViewTop + $('#' + divID).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}。
基于此答案的一个示例,用于检查元素是否75%可见(即少于25%的元素不在屏幕上)。
1
2
3
4
5
6
7
8
9
10
11function isScrolledIntoView(el) {
// check for 75% visible
var percentVisible = 0.75;
var elemTop = el.getBoundingClientRect().top;
var elemBottom = el.getBoundingClientRect().bottom;
var elemHeight = el.getBoundingClientRect().height;
var overhang = elemHeight * (1 - percentVisible);
var isVisible = (elemTop >= -overhang) && (elemBottom <= window.innerHeight + overhang);
return isVisible;
}。
可滚动DIV(容器)的简单修改
1
2
3
4
5
6var isScrolledIntoView = function(elem, container) {
var containerHeight = $(container).height();
var elemTop = $(elem).position().top;
var elemBottom = elemTop + $(elem).height();
return (elemBottom > 0 && elemTop < containerHeight);
}号
注意:如果元素大于滚动分区,则此操作不起作用。
我修改了这个简短的jquery函数扩展,您可以随意使用(MIT许可证)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22/**
* returns true if an element is visible, with decent performance
* @param [scope] scope of the render-window instance; default: window
* @returns {boolean}
*/
jQuery.fn.isOnScreen = function(scope){
var element = this;
if(!element){
return;
}
var target = $(element);
if(target.is(':visible') == false){
return false;
}
scope = $(scope || window);
var top = scope.scrollTop();
var bot = top + scope.height();
var elTop = target.offset().top;
var elBot = elTop + target.height();
return ((elBot <= bot) && (elTop >= top));
};我更喜欢使用jquery expr
1
2
3
4
5
6
7
8
9
10
11
12
13
14jQuery.extend(jQuery.expr[':'], {
inview: function (elem) {
var t = $(elem);
var offset = t.offset();
var win = $(window);
var winST = win.scrollTop();
var elHeight = t.outerHeight(true);
if ( offset.top > winST - elHeight && offset.top < winST + elHeight + win.height()) {
return true;
}
return false;
}
});所以你可以这样用
1
2
3$(".my-elem:inview"); //returns only element that is in view
$(".my-elem").is(":inview"); //check if element is in view
$(".my-elem:inview").length; //check how many elements are in view您可以轻松地在
scroll 事件函数等中添加此类代码,以便在每次用户滚动视图时检查它。- 使用
expr 检查元素的滚动可见性有很大的缺点,因为它可能只对不在滚动容器中的元素有效,因为您使用window 对象作为硬编码范围。
我已经为这个任务编写了一个组件,它可以非常快速地处理大量元素(对于速度较慢的移动设备上的1000个元素,调到小于10毫秒)。
它适用于您可以访问的每种类型的滚动容器——窗口、HTML元素、嵌入的iframe、生成的子窗口——并且在检测到的内容方面非常灵活(完全或部分可见性、边框或内容框、自定义公差带等)。
一个巨大的,主要是自动生成的测试套件可以确保它像广告中那样跨浏览器工作。
如果您愿意,可以试一试:jquery.isinview。否则,您可能会在源代码中找到灵感,例如这里。
我在寻找一种方法来查看元素是否很快就会出现,所以通过扩展上面的代码片段,我成功地做到了这一点。我想我会把这个留在这里,以防它能帮助别人。
elm=要检查的元素是否在视图中
ScrollElement=可以传递窗口或具有滚动的父元素
offset=如果希望在元素在屏幕中出现之前在200px之外时激发它,则通过200
1
2
3
4
5
6
7
8
9
10
11function isScrolledIntoView(elem, scrollElement, offset)
{
var $elem = $(elem);
var $window = $(scrollElement);
var docViewTop = $window.scrollTop();
var docViewBottom = docViewTop + $window.height();
var elemTop = $elem.offset().top;
var elemBottom = elemTop + $elem.height();
return (((elemBottom+offset) >= docViewBottom) && ((elemTop-offset) <= docViewTop)) || (((elemBottom-offset) <= docViewBottom) && ((elemTop+offset) >= docViewTop));
}。
这个问题有30多个答案,没有一个使用我一直使用的非常简单的纯JS解决方案。没有必要仅仅为了解决这个问题而加载jquery,因为许多其他人正在推送它。
为了判断元素是否在视区中,我们必须首先确定元素在主体中的位置。我们不需要像我曾经想的那样递归地做这个。相反,我们可以使用
element.getBoundingClientRect() 。1pos = elem.getBoundingClientRect().top - document.body.getBoundingClientRect().top;该值是对象顶部和主体顶部之间的Y差。
然后我们必须判断元素是否在视图中。大多数实现都会询问整个元素是否在视区内,所以这就是我们要讨论的内容。
首先,窗口的顶部位置是:
window.scrollY 。我们可以通过将窗口的高度添加到其顶部位置来获取窗口的底部位置:
1var window_bottom_position = window.scrollY + window.innerHeight;号
让我们创建一个简单的函数来获取元素的顶部位置:
1
2
3function getElementWindowTop(elem){
return elem && typeof elem.getBoundingClientRect === 'function' ? elem.getBoundingClientRect().top - document.body.getBoundingClientRect().top : 0;
}此函数将返回元素在窗口中的顶部位置,或者如果使用
.getBoundingClientRect() 方法传递元素以外的其他元素,它将返回0 。这种方法已经存在很长时间了,所以您不必担心浏览器不支持它。现在,元素的首要位置是:
1var element_top_position = getElementWindowTop(element);。
和或元素的底部位置是:
1var element_bottom_position = element_top_position + element.clientHeight;现在,我们可以通过检查元素的底部位置是否低于视区的顶部位置以及检查元素的顶部位置是否高于视区的底部位置来确定元素是否在视区内:
1
2
3
4
5if(element_bottom_position >= window.scrollY
&& element_top_position <= window_bottom_position){
//element is in view
else
//element is not in view。
从那里,您可以执行逻辑来添加或删除元素上的
in-view 类,然后您可以在CSS中使用转换效果处理该类。我很惊讶我在任何地方都没有找到这个解决方案,但是我相信这是最干净和最有效的解决方案,并且不需要您加载jquery!
- 很好的解释!但是已经有了答案,就像艾丽的答案一样
- @多梅西,嗯,我不知怎么地跳过了。很公平。不过,谢谢你指出这一点。很高兴看到这样做了。
如果元素的任何部分在页面上可见,则此方法将返回true。在我的情况下效果更好,可能会帮助其他人。
1
2
3
4
5
6
7
8
9
10
11
12function isOnScreen(element) {
var elementOffsetTop = element.offset().top;
var elementHeight = element.height();
var screenScrollTop = $(window).scrollTop();
var screenHeight = $(window).height();
var scrollIsAboveElement = elementOffsetTop + elementHeight - screenScrollTop >= 0;
var elementIsVisibleOnScreen = screenScrollTop + screenHeight - elementOffsetTop >= 0;
return scrollIsAboveElement && elementIsVisibleOnScreen;
}。
我只是想分享一下,我把这个和我的脚本结合起来,移动这个DIV,使它始终保持在视图中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30$("#accordion").on('click', '.subLink', function(){
var url = $(this).attr('src');
updateFrame(url);
scrollIntoView();
});
$(window).scroll(function(){
changePos();
});
function scrollIntoView()
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $("#divPos").offset().top;
var elemBottom = elemTop + $("#divPos").height();
if (elemTop < docViewTop){
$("#divPos").offset({top:docViewTop});
}
}
function changePos(){
var scrTop = $(window).scrollTop();
var frmHeight = $("#divPos").height()
if ((scrTop < 200) || (frmHeight > 800)){
$("#divPos").attr("style","position:absolute;");
}else{
$("#divPos").attr("style","position:fixed;top:5px;");
}
}此答案的更有效版本:
1
2
3
4
5
6
7
8
9/**
* Is element within visible region of a scrollable container
* @param {HTMLElement} el - element to test
* @returns {boolean} true if within visible region, otherwise false
*/
function isScrolledIntoView(el) {
var rect = el.getBoundingClientRect();
return (rect.top >= 0) && (rect.bottom <= window.innerHeight);
}号
在使用ES6的现代浏览器中,我们可以这样做:
1
2
3
4
5
6const isFullySeen = el => el &&
typeof el.getBoundingClientRect === 'function' &&
el.getBoundingClientRect()['bottom'] + window.scrollY <=
window.innerHeight + window.scrollY &&
el.getBoundingClientRect()['top'] + window.scrollY <=
window.innerHeight + window.scrollY;号
唯一对我来说一直有效的插件是:https://github.com/customd/jquery-visible
我最近把这个插件移植到了GWT,因为我不想仅仅为了使用插件而将jquery作为依赖项添加。这是我的(简单)端口(仅包括我的用例所需的功能):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public static boolean isVisible(Element e)
{
//vp = viewPort, b = bottom, l = left, t = top, r = right
int vpWidth = Window.getClientWidth();
int vpHeight = Window.getClientHeight();
boolean tViz = ( e.getAbsoluteTop() >= 0 && e.getAbsoluteTop()< vpHeight);
boolean bViz = (e.getAbsoluteBottom() > 0 && e.getAbsoluteBottom() <= vpHeight);
boolean lViz = (e.getAbsoluteLeft() >= 0 && e.getAbsoluteLeft() < vpWidth);
boolean rViz = (e.getAbsoluteRight() > 0 && e.getAbsoluteRight() <= vpWidth);
boolean vVisible = tViz && bViz;
boolean hVisible = lViz && rViz;
return hVisible && vVisible;
}检查元素是否在屏幕上,而不是检查DIV是否完全在屏幕上的公认答案方法(如果DIV大于屏幕,则不起作用)。在纯JavaScript中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31/**
* Checks if element is on the screen (Y axis only), returning true
* even if the element is only partially on screen.
*
* @param element
* @returns {boolean}
*/
function isOnScreenY(element) {
var screen_top_position = window.scrollY;
var screen_bottom_position = screen_top_position + window.innerHeight;
var element_top_position = element.offsetTop;
var element_bottom_position = element_top_position + element.offsetHeight;
return (inRange(element_top_position, screen_top_position, screen_bottom_position)
|| inRange(element_bottom_position, screen_top_position, screen_bottom_position));
}
/**
* Checks if x is in range (in-between) the
* value of a and b (in that order). Also returns true
* if equal to either value.
*
* @param x
* @param a
* @param b
* @returns {boolean}
*/
function inRange(x, a, b) {
return (x >= a && x <= b);
}。
制作了一个简单的插件,用于检测元素是否在可滚动容器中可见。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19$.fn.isVisible = function(){
var win;
if(!arguments[0])
{
console.error('Specify a target;');
return false;
}
else
{
win = $(arguments[0]);
}
var viewport = {};
var bounds = this.offset();
bounds.right = bounds.left + this.outerWidth();
bounds.bottom = bounds.top + this.outerHeight();
viewport.bottom = win.height() + win.offset().top;
return (!( bounds.top > viewport.bottom) && (win.offset().top < bounds.bottom));
};像这样叫它
$('elem_to_check').isVisible('scrollable_container'); 。希望能有所帮助。
仅限javascript:)
1
2
3
4
5
6
7
8
9
10function isInViewport(element) {
var rect = element.getBoundingClientRect();
var html = document.documentElement;
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || html.clientHeight) &&
rect.right <= (window.innerWidth || html.clientWidth)
);
}号
- 江户十一〔二〕是从哪里来的?
在运行了一些没有效果的代码之后。这就是我使用jquery在垂直滚动可见性上的工作原理。将"footerplace"替换为要垂直跟踪的元素。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18jQuery.expr.filters.offscreen = function(el) {
var rect = el.getBoundingClientRect();
console.log(rect)
console.log('window height', $(window).height());
return (
(rect.top <= $(window).height()) && (rect.bottom <= $(window).height())
);
};
$(document).scroll(function(){
if ($('#footerplace').is(':offscreen')){
console.log('this is true');
$('#footerplace').is(':offscreen');
} else {
console.log('this is false');
$('#footerplace').is(':offscreen');
}号
Copyright © 码农家园 联系:[email protected] - 在所有情况下,它似乎都不起作用。例如,即使在我滚动到窗口的最底部之后,我还是得到了: