TLDR:
受这个问题和我自己的项目中类似功能的必要性的启发,我根据下面的代码编写了module/jQuery plugin。如果您对“方法”不感兴趣,只需下载它或使用您最喜欢的包管理器安装即可。
原答案:
answer provided by exabyssus 在大多数情况下都能正常工作,除非元素的顶部或底部都不可见,例如当元素高度大于窗口高度时。
这是一个更新版本,它考虑了这种情况并使用getBoundingClientRect,即supported right the way down to IE8:
// Usage: var $element = getMostVisible($('.elements' ));
function getMostVisible($elements) {
var element,
viewportHeight = $(window).height(),
max = 0;
$elements.each(function() {
var visiblePx = getVisibleHeightPx($(this), viewportHeight);
if (visiblePx > max) {
max = visiblePx;
element = this;
}
});
return $elements.filter(element);
}
function getVisibleHeightPx($element, viewportHeight) {
var rect = $element.get(0).getBoundingClientRect(),
height = rect.bottom - rect.top,
visible = {
top: rect.top >= 0 && rect.top < viewportHeight,
bottom: rect.bottom > 0 && rect.bottom < viewportHeight
},
visiblePx = 0;
if (visible.top && visible.bottom) {
// Whole element is visible
visiblePx = height;
} else if (visible.top) {
visiblePx = viewportHeight - rect.top;
} else if (visible.bottom) {
visiblePx = rect.bottom;
} else if (height > viewportHeight && rect.top < 0) {
var absTop = Math.abs(rect.top);
if (absTop < height) {
// Part of the element is visible
visiblePx = height - absTop;
}
}
return visiblePx;
}
这会根据像素返回最可见的元素,而不是元素高度的百分比,这非常适合我的用例。如果需要,可以轻松修改它以返回百分比。
您也可以将其用作 jQuery 插件,这样您就可以使用 $('.elements').mostVisible() 获取最可见的元素,而不是将元素传递给函数。为此,您只需将其包含在上面的两个函数中:
$.fn.mostVisible = function() {
return getMostVisible(this);
};
有了它,您可以链接您的方法调用,而不必将元素保存到变量中:
$('.elements').mostVisible().addClass('most-visible').html('I am most visible!');
所有内容都包含在一个小演示中,您可以在 SO 上试用:
(function($) {
'use strict';
$(function() {
$(window).on('scroll', function() {
$('.the-divs div').html('').removeClass('most-visible').mostVisible().addClass('most-visible').html('I am most visible!');
});
});
function getMostVisible($elements) {
var element,
viewportHeight = $(window).height(),
max = 0;
$elements.each(function() {
var visiblePx = getVisibleHeightPx($(this), viewportHeight);
if (visiblePx > max) {
max = visiblePx;
element = this;
}
});
return $elements.filter(element);
}
function getVisibleHeightPx($element, viewportHeight) {
var rect = $element.get(0).getBoundingClientRect(),
height = rect.bottom - rect.top,
visible = {
top: rect.top >= 0 && rect.top < viewportHeight,
bottom: rect.bottom > 0 && rect.bottom < viewportHeight
},
visiblePx = 0;
if (visible.top && visible.bottom) {
// Whole element is visible
visiblePx = height;
} else if (visible.top) {
visiblePx = viewportHeight - rect.top;
} else if (visible.bottom) {
visiblePx = rect.bottom;
} else if (height > viewportHeight && rect.top < 0) {
var absTop = Math.abs(rect.top);
if (absTop < height) {
// Part of the element is visible
visiblePx = height - absTop;
}
}
return visiblePx;
}
$.fn.mostVisible = function() {
return getMostVisible(this);
}
})(jQuery);
.top {
height: 900px;
background-color: #999
}
.middle {
height: 200px;
background-color: #eee
}
.bottom {
height: 600px;
background-color: #666
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="the-divs">
<div class="top"></div>
<div class="middle"></div>
<div class="bottom"></div>
</div>