我正在通过 AJAX 加载元素。其中一些只有在您向下滚动页面时才可见。有什么方法可以知道元素现在是否在页面的可见部分中?
46 回答
这应该可以解决问题:
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));
}
简单的实用函数 这将允许您调用一个实用函数,该函数接受您正在寻找的元素以及您希望该元素是完全可见还是部分可见。
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();
用法
var isElementInView = Utils.isElementInView($('#flyout-left-container'), false);
if (isElementInView) {
console.log('in view');
} else {
console.log('out of view');
}
香草的这个答案:
function 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;
}
更新:使用IntersectionObserver
到目前为止我发现的最好的方法是jQuery 出现插件。奇迹般有效。
模仿自定义的“出现”事件,当元素滚动到视图中或以其他方式对用户可见时触发。
$('#foo').appear(function() { $(this).text('Hello world'); });
此插件可用于防止对隐藏或可见区域之外的内容的不必要请求。
使用IntersectionObserver API
(在现代浏览器中原生)
使用观察者可以轻松高效地确定元素是否在视口中或任何可滚动容器中可见。
消除了附加scroll
事件和手动检查事件回调的需要,这样更有效:
// define an observer instance
var observer = new IntersectionObserver(onIntersection, {
root: null, // default is the viewport
threshold: .5 // percentage of taregt's visible area. Triggers "onIntersection"
})
// callback is called on intersection change
function onIntersection(entries, opts){
entries.forEach(entry =>
entry.target.classList.toggle('visible', entry.isIntersecting)
)
}
// Use the observer to observe an element
observer.observe( document.querySelector('.box') )
// To stop observing:
// observer.unobserve(entry.target)
span{ position:fixed; top:0; left:0; }
.box{ width:100px; height:100px; background:red; margin:1000px; transition:.75s; }
.box.visible{ background:green; border-radius:50%; }
<span>Scroll both Vertically & Horizontally...</span>
<div class='box'></div>
现代浏览器支持,包括移动浏览器。IE 中不支持 -查看浏览器支持表
这是我的纯 JavaScript 解决方案,如果它也隐藏在可滚动容器中,它也可以工作。
演示在这里(也尝试调整窗口大小)
var 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:更新为在屏幕上方滚动出视图时处理。
普通香草检查元素(el
)是否在可滚动的 div(holder
)中可见
function 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 一起使用:
var el = $('tr:last').get(0);
var holder = $('table').get(0);
var isVisible = isScrolledIntoView(el, holder);
jQuery Waypoints 插件在这里非常好用。
$('.entry').waypoint(function() {
alert('You have scrolled to an entry.');
});
插件网站上有一些示例。
怎么样
function isInView(elem){
return $(elem).offset().top - $(window).scrollTop() < $(elem).height() ;
}
之后,一旦元素出现在这样的视图中,您就可以触发任何您想要的东西
$(window).scroll(function(){
if (isInView($('.classOfDivToCheck')))
//fire whatever you what
dothis();
})
这对我来说很好
Tweeked Scott Dowding 为我的要求提供的很酷的功能 - 这用于查找元素是否刚刚滚动到屏幕中,即它的顶部边缘。
function isScrolledIntoView(elem)
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
return ((elemTop <= docViewBottom) && (elemTop >= docViewTop));
}
WebResourcesDepot前段时间使用jQuery编写了一个在滚动时加载的脚本。你可以在这里查看他们的现场演示。他们的功能的牛肉是这样的:
$(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();
});
};
这里的大多数答案都没有考虑到一个元素也可以被隐藏,因为它被滚动到一个 div 的视图之外,而不仅仅是整个页面。
为了覆盖这种可能性,您基本上必须检查元素是否位于每个父元素的边界内。
该解决方案正是这样做的:
function(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 中对其进行了测试。
isScrolledIntoView是一个非常需要的功能,所以我试了一下,它适用于不高于视口的元素,但如果元素比视口大,它就不起作用。要解决此问题,请轻松更改条件
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
对此:
return (docViewBottom >= elemTop && docViewTop <= elemBottom);
在此处查看演示:http: //jsfiddle.net/RRSmQ/
这是另一个解决方案:
<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('<div class="alert alert-success">target element is visible on screen</div>'); // log info
} else {
$('.log').html('<div class="alert">target element is not visible on screen</div>'); // log info
}
}
$(window).on('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('<div class="alert alert-success">target element is visible on screen</div>'); // log info
} else {
$('.log').html('<div class="alert">target element is not visible on screen</div>'); // log info
}
}
});
</script>
这会考虑元素具有的任何填充、边框或边距,以及大于视口本身的元素。
function 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);
}
要调用它,请使用以下内容:
var $myElement = $('#my-element'),
canUserSeeIt = inViewport($myElement);
console.log(canUserSeeIt); // true, if element is visible; false otherwise
function 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));
}
有一个名为inview的 jQuery 插件,它添加了一个新的“inview”事件。
下面是一些不使用事件的 jQuery 插件的代码:
$.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 );
我在这里的评论中发现了这一点(http://remysharp.com/2009/01/26/element-in-view-event-plugin/)一个叫詹姆斯的家伙
我需要检查可滚动 DIV 容器内元素的可见性
//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);
}
在这个很好的答案的基础上,您可以使用 ES2015+ 进一步简化它:
function isScrolledIntoView(el) {
const { top, bottom } = el.getBoundingClientRect()
return top >= 0 && bottom <= window.innerHeight
}
如果您不关心顶部超出窗口而只关心底部已被查看,则可以将其简化为
function isSeen(el) {
return el.getBoundingClientRect().bottom <= window.innerHeight
}
甚至是单线
const isSeen = el => el.getBoundingClientRect().bottom <= window.innerHeight
我的应用程序中有这样一个方法,但它不使用 jQuery:
/* 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));
}
编辑:此方法适用于 IE(至少版本 6)。阅读评论以了解与 FF 的兼容性。
如果你想调整它以在另一个 div 中滚动项目,
function 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));
}
您可以使用 jquery 插件“onScreen”来检查滚动时元素是否在当前视口中。The plugin sets the ":onScreen" of the selector to true when the selector appears on the screen. 这是您可以包含在项目中的插件的链接。“ http://benpickles.github.io/onScreen/jquery.onscreen.min.js ”
您可以尝试以下对我有用的示例。
$(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 代码:
<div id="div1" style="width: 400px; height: 1000px; padding-top: 20px; position: relative; top: 45px"></div> <br>
<hr /> <br>
<div id="div2" style="width: 400px; height: 200px"></div>
CSS:
#div1 {
background-color: red;
}
#div2 {
background-color: green;
}
一个基于此答案的示例,用于检查元素是否 75% 可见(即不到 25% 的元素不在屏幕上)。
function 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;
}
此答案的更有效版本:
/**
* 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);
}
我为此找到的最简单的解决方案是Intersection Observer API:
var observer = new IntersectionObserver(function(entries) {
if(entries[0].isIntersecting === true)
console.log('Element has just become visible in screen');
}, { threshold: [0] });
observer.observe(document.querySelector("#main-container"));
修改了接受的答案,以便元素必须将其显示属性设置为“无”以外的其他值,以使质量可见。
function 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);
}
这是一种使用 Mootools 在水平、垂直或两者中实现相同目标的方法。
Element.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);
}});
如果元素的任何部分在页面上可见,此方法将返回 true。它在我的情况下效果更好,可能会帮助其他人。
function 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;
}
我更喜欢使用 jQuery expr
jQuery.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;
}
});
所以你可以这样使用它
$(".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
以在每次用户滚动视图时检查它。
这个问题有 30 多个答案,但没有一个使用我一直在使用的极其简单的纯 JS 解决方案。没有必要仅仅为了解决这个问题而加载 jQuery,因为许多其他人都在推动。
为了判断元素是否在视口内,我们必须首先确定元素在主体内的位置。我们不需要像我曾经认为的那样递归地执行此操作。相反,我们可以使用element.getBoundingClientRect()
.
pos = elem.getBoundingClientRect().top - document.body.getBoundingClientRect().top;
该值是对象顶部和主体顶部之间的 Y 差。
然后我们必须判断该元素是否在视野范围内。大多数实现都会询问整个元素是否在视口内,所以这就是我们要介绍的内容。
首先,窗口的顶部位置是:window.scrollY
。
我们可以通过将窗口的高度添加到其顶部位置来获得窗口的底部位置:
var window_bottom_position = window.scrollY + window.innerHeight;
让我们创建一个简单的函数来获取元素的顶部位置:
function getElementWindowTop(elem){
return elem && typeof elem.getBoundingClientRect === 'function' ? elem.getBoundingClientRect().top - document.body.getBoundingClientRect().top : 0;
}
此函数将返回元素在窗口中的顶部位置,或者如果您使用该方法0
传递元素以外的其他内容,它将返回。.getBoundingClientRect()
这种方法已经存在了很长时间,因此您不必担心您的浏览器不支持它。
现在,我们元素的顶部位置是:
var element_top_position = getElementWindowTop(element);
And or 元素的底部位置是:
var element_bottom_position = element_top_position + element.clientHeight;
现在我们可以通过检查元素的底部位置是否低于视口的顶部位置以及检查元素的顶部位置是否高于视口的底部位置来确定元素是否在视口内:
if(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!
可滚动div(容器)的简单修改
var isScrolledIntoView = function(elem, container) {
var containerHeight = $(container).height();
var elemTop = $(elem).position().top;
var elemBottom = elemTop + $(elem).height();
return (elemBottom > 0 && elemTop < containerHeight);
}
注意:如果元素大于可滚动的 div,这不起作用。
我改编了这个简短的 jQuery 函数扩展,您可以随意使用(MIT 许可证)。
/**
* 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));
};
我一直在寻找一种方法来查看该元素是否会很快出现,因此通过扩展上面的片段,我设法做到了。以为我会把它留在这里以防万一它会帮助某人
elm = 是你要检查的元素在视图中
scrollElement = 您可以传递窗口或具有滚动的父元素
offset = 如果您希望它在元素在屏幕中之前 200px 时触发,则传递 200
function 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));
}
我们可以使用ES6在现代浏览器中做这样的事情:
const 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;
我添加了我的代码修改。不幸的是,我可以看到每个人的版本,每个人都忽略了 debance 功能的使用。哪个答案是让您的事件不触发,例如,滚动时每秒 200 次。
$(window).scroll(function(){
if (isInView($('.class'))){
debounce(
someFunction(), 5
)
}
});
function isInView(elem){
if(document.documentElement.clientWidth > 991){
return $(elem).offset().top - $(window).scrollTop() < $(elem).height();
}else {
doSometing;
}
}
Javascript代码可以写成:
window.addEventListener('scroll', function() {
var element = document.querySelector('#main-container');
var position = element.getBoundingClientRect();
// checking whether fully visible
if(position.top >= 0 && position.bottom <= window.innerHeight) {
console.log('Element is fully visible in screen');
}
// checking for partial visibility
if(position.top < window.innerHeight && position.bottom >= 0) {
console.log('Element is partially visible in screen');
}
});
并在 react js 中写成:
componentDidMount() {
window.addEventListener('scroll', this.isScrolledIntoView);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.isScrolledIntoView);
}
isScrolledIntoView() {
var element = document.querySelector('.element');
var position = element.getBoundingClientRect();
// checking whether fully visible
if (position.top >= 0 && position.bottom <= window.innerHeight) {
console.log('Element is fully visible in screen');
}
// checking for partial visibility
if (position.top < window.innerHeight && position.bottom >= 0) {
console.log('Element is partially visible in screen');
}
}
我只是想分享一下我将它与我的脚本结合以移动 div 以便它始终保持在视图中:
$("#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;");
}
}
在打字稿上
private readonly isElementInViewPort = (el: HTMLElement): boolean => {
const rect = el.getBoundingClientRect();
const elementTop = rect.top;
const elementBottom = rect.bottom;
const scrollPosition = el?.scrollTop || document.body.scrollTop;
return (
elementBottom >= 0 &&
elementTop <= document.documentElement.clientHeight &&
elementTop + rect.height > elementTop &&
elementTop <= elementBottom &&
elementTop >= scrollPosition
);
};
唯一对我有用的插件是:https ://github.com/customd/jquery-visible
我最近将此插件移植到GWT,因为我不想将 jquery 添加为仅用于使用该插件的依赖项。这是我的(简单)端口(仅包括我的用例所需的功能):
public 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 中:
/**
* 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);
}
制作了一个简单的插件来检测元素是否在可滚动容器中可见
$.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');
希望它会有所帮助。
jquery scrollspy 插件可以让你轻松做到这一点。 https://github.com/thesmart/jquery-scrollspy
$('.tile').on('scrollSpy:enter', function() {
console.log('enter:', $(this).attr('id'));
});
$('.tile').on('scrollSpy:exit', function() {
console.log('exit:', $(this).attr('id'));
});
$('.tile').scrollSpy();
唯一对我有用的解决方案是(当 $("#elementToCheck") 可见时返回 true):
$(document).scrollTop()+window.innerHeight+$("#elementToCheck").height()>$("#elementToCheck").offset().top
其他答案通常不检查元素是否沿 X 轴在视图中,即可能在当前视口 Y 范围内,但在 X 范围之外。如果项目的任何部分显示在视口中,此函数会检查 X 和 Y:
function checkElInView(el) {
if (!el || !typeof el.getBoundingClientRect === "function") return false;
const r = el.getBoundingClientRect();
const vw = document.documentElement.clientWidth;
const vh = document.documentElement.clientHeight;
const inViewX = (r.left > 0 && r.left < vw) || (r.right < vw && r.right > 0);
const inViewY = (r.top > 0 && r.top < vh) || (r.bottom < vh && r.bottom > 0);
return inViewX && inViewY;
}
仅限 Javascript :)
function 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”替换为您要垂直跟踪的元素。
jQuery.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');
}