私は次の問題に対する良い解決策を見つける必要があります。要素がページまたはブラウザウィンドウのビューポートの内側にあるか外側にあるかを追跡することについて質問する人がたくさんいます。このアクションを複製できるようにする必要がありますが、スクロールするDIV内で、たとえばoverflow:scrollを使用します。この特定の行動の良い例を知っている人はいますか?
前もって感謝します。
以前に同じ問題が発生しましたが、次の関数になりました。最初のパラメータは要素をチェックするためのもので、2番目は要素が部分的に表示されているかどうかをチェックするためのものです。垂直方向のチェック専用です。拡張できます。水平スクロールをチェックします。
function checkInView(elem,partial)
{
var container = $(".scrollable");
var contHeight = container.height();
var contTop = container.scrollTop();
var contBottom = contTop + contHeight ;
var elemTop = $(elem).offset().top - container.offset().top;
var elemBottom = elemTop + $(elem).height();
var isTotal = (elemTop >= 0 && elemBottom <=contHeight);
var isPart = ((elemTop < 0 && elemBottom > 0 ) || (elemTop > 0 && elemTop <= container.height())) && partial ;
return isTotal || isPart ;
}
jsFiddle で確認してください。
これは、jQueryに依存せず、部分的なインビュー検出と上部のアウトオブビューのサポートにいくつかの修正を加えた、受け入れられた回答の純粋なjavascriptバージョンです。
function checkInView(container, element, partial) {
//Get container properties
let cTop = container.scrollTop;
let cBottom = cTop + container.clientHeight;
//Get element properties
let eTop = element.offsetTop;
let eBottom = eTop + element.clientHeight;
//Check if in view
let isTotal = (eTop >= cTop && eBottom <= cBottom);
let isPartial = partial && (
(eTop < cTop && eBottom > cTop) ||
(eBottom > cBottom && eTop < cBottom)
);
//Return outcome
return (isTotal || isPartial);
}
また、ボーナスとして、この関数は、要素が表示されていない場合(部分的または完全)に表示されていることを確認します。
function ensureInView(container, element) {
//Determine container top and bottom
let cTop = container.scrollTop;
let cBottom = cTop + container.clientHeight;
//Determine element top and bottom
let eTop = element.offsetTop;
let eBottom = eTop + element.clientHeight;
//Check if out of view
if (eTop < cTop) {
container.scrollTop -= (cTop - eTop);
}
else if (eBottom > cBottom) {
container.scrollTop += (eBottom - cBottom);
}
}
ベストアンサーに基づいています。要素が部分的に表示されているかどうかを通知するだけではありません。要素がx%を超えて表示されているかどうかを示すパーセンテージ(0〜100)を渡すことができるように、少し余分に追加しました。
function (container, element, partial) {
var cTop = container.scrollTop;
var cBottom = cTop + container.clientHeight;
var eTop = element.offsetTop;
var eBottom = eTop + element.clientHeight;
var isTotal = (eTop >= cTop && eBottom <= cBottom);
var isPartial;
if (partial === true) {
isPartial = (eTop < cTop && eBottom > cTop) || (eBottom > cBottom && eTop < cBottom);
} else if(typeof partial === "number"){
if (eTop < cTop && eBottom > cTop) {
isPartial = ((eBottom - cTop) * 100) / element.clientHeight > partial;
} else if (eBottom > cBottom && eTop < cBottom){
isPartial = ((cBottom - eTop) * 100) / element.clientHeight > partial;
}
}
return (isTotal || isPartial);
}
投稿された純粋なJavaScriptバージョンに小さな変更を加えることで、この作業を行うことができました
function checkInView(container, element, partial) {
//Get container properties
let cTop = container.scrollTop;
let cBottom = cTop + container.clientHeight;
//Get element properties
let eTop = element.offsetTop - container.offsetTop; // change here
let eBottom = eTop + element.clientHeight;
//Check if in view
let isTotal = (eTop >= cTop && eBottom <= cBottom);
let isPartial = partial && (
(eTop < cTop && eBottom > cTop) ||
(eBottom > cBottom && eTop < cBottom)
);
//Return outcome
return (isTotal || isPartial);
}
これが純粋なJavaScriptソリューションです。
function elementIsVisible(element, container, partial) {
var contHeight = container.offsetHeight,
elemTop = offset(element).top - offset(container).top,
elemBottom = elemTop + element.offsetHeight;
return (elemTop >= 0 && elemBottom <= contHeight) ||
(partial && ((elemTop < 0 && elemBottom > 0 ) || (elemTop > 0 && elemTop <= contHeight)))
}
// checks window
function isWindow( obj ) {
return obj != null && obj === obj.window;
}
// returns corresponding window
function getWindow( elem ) {
return isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
}
// taken from jquery
// @returns {{top: number, left: number}}
function offset( elem ) {
var docElem, win,
box = { top: 0, left: 0 },
doc = elem && elem.ownerDocument;
docElem = doc.documentElement;
if ( typeof elem.getBoundingClientRect !== typeof undefined ) {
box = elem.getBoundingClientRect();
}
win = getWindow( doc );
return {
top: box.top + win.pageYOffset - docElem.clientTop,
left: box.left + win.pageXOffset - docElem.clientLeft
};
};
私は最後の答えでjqueryプラグインを作成しました:
(function($) {
$.fn.reallyVisible = function(opt) {
var options = $.extend({
cssChanges:[
{ name : 'visibility', states : ['hidden','visible'] }
],
childrenClass:'mentioners2',
partialview : true
}, opt);
var container = $(this);
var contHeight;
var contTop;
var contBottom;
var _this = this;
var _children;
this.checkInView = function(elem,partial){
var elemTop = $(elem).offset().top - container.offset().top;
var elemBottom = elemTop + $(elem).height();
var isTotal = (elemTop >= 0 && elemBottom <=contHeight);
var isPart = ((elemTop < 0 && elemBottom > 0 ) || (elemTop > 0 && elemTop <= container.height())) && partial ;
return isTotal || isPart ;
}
this.bind('restoreProperties',function(){
$.each(_children,function(i,elem){
$.each(options.cssChanges,function(i,_property){
$(elem).css(_property.name,_property.states[1]);
});
});
_children = null;
});
return this.each(function(){
contHeight = container.height();
contTop = container.scrollTop();
contBottom = contTop + contHeight ;
_children = container.children("."+options.childrenClass);
$.each(_children,function(i,elem){
var res = _this.checkInView(elem,options.partialview);
if( !res ){
$.each(options.cssChanges,function(i,_property){
$(elem).css(_property.name,_property.states[0]);
});
}
});
});
}
})(jQuery);
あなたはこれを試すことができます
function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + window.innerHeight;
var el = $(elem);
var elemTop = el.offset().top;
var elemBottom = elemTop + el.height();
var elemDisplayNotNone = el.css("display") !== "none";
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop) && elemDisplayNotNone);
}
例えば:
isScrolledIntoView('#button')