簡體   English   中英

有多少元素在視口中可見

[英]How much of an element is visible in viewport

頁面上有一個div (棕色矩形)。 頁面高於視口(橙色矩形),因此可以滾動,這意味着div可能僅部分顯示或根本不顯示。

元素可見性

判斷視口中可見div百分比的最簡單算法是什么?

(為了使事情更容易, div總是水平地適合視口,因此在計算時只需要考慮 Y 軸。)

查看小提琴中的另一個示例: https : //jsfiddle.net/1hfxom6h/3/

 /*jslint browser: true*/ /*global jQuery, window, document*/ (function ($) { 'use strict'; var results = {}; function display() { var resultString = ''; $.each(results, function (key) { resultString += '(' + key + ': ' + Math.round(results[key]) + '%)'; }); $('p').text(resultString); } function calculateVisibilityForDiv(div$) { var windowHeight = $(window).height(), docScroll = $(document).scrollTop(), divPosition = div$.offset().top, divHeight = div$.height(), hiddenBefore = docScroll - divPosition, hiddenAfter = (divPosition + divHeight) - (docScroll + windowHeight); if ((docScroll > divPosition + divHeight) || (divPosition > docScroll + windowHeight)) { return 0; } else { var result = 100; if (hiddenBefore > 0) { result -= (hiddenBefore * 100) / divHeight; } if (hiddenAfter > 0) { result -= (hiddenAfter * 100) / divHeight; } return result; } } function calculateAndDisplayForAllDivs() { $('div').each(function () { var div$ = $(this); results[div$.attr('id')] = calculateVisibilityForDiv(div$); }); display(); } $(document).scroll(function () { calculateAndDisplayForAllDivs(); }); $(document).ready(function () { calculateAndDisplayForAllDivs(); }); }(jQuery));
 div { height:200px; width:300px; border-width:1px; border-style:solid; } p { position: fixed; left:320px; top:4px; }
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="div1">div1</div> <div id="div2">div2</div> <div id="div3">div3</div> <div id="div4">div4</div> <p id="result"></p>

這是一個片段,說明了如何計算它。

我已將 % 值放在框中以提高可讀性,它甚至有點“跟隨”視口 ^^ :

小提琴版

 function listVisibleBoxes() { var results = []; $("section").each(function () { var screenTop = document.documentElement.scrollTop; var screenBottom = document.documentElement.scrollTop + $(window).height(); var boxTop = $(this).offset().top; var boxHeight = $(this).height(); var boxBottom = boxTop + boxHeight; if(boxTop > screenTop) { if(boxBottom < screenBottom) { //full box results.push(this.id + "-100%"); $(this).html("100%").css({ "line-height": "50vh" }); } else if(boxTop < screenBottom) { //partial (bottom) var percent = Math.round((screenBottom - boxTop) / boxHeight * 100) + "%"; var lineHeight = Math.round((screenBottom - boxTop) / boxHeight * 50) + "vh"; results.push(this.id + "-" + percent); $(this).html(percent).css({ "line-height": lineHeight }); } } else if(boxBottom > screenTop) { //partial (top) var percent = Math.round((boxBottom - screenTop) / boxHeight * 100) + "%"; var lineHeight = 100 - Math.round((boxBottom - screenTop) / boxHeight * 50) + "vh"; results.push(this.id + "-" + percent); $(this).html(percent).css({ "line-height": lineHeight }); } }); $("#data").html(results.join(" | ")); } $(function () { listVisibleBoxes(); $(window).on("scroll", function() { listVisibleBoxes(); }); });
 body { background-color: rgba(255, 191, 127, 1); font-family: Arial, sans-serif; } section { background-color: rgba(175, 153, 131, 1); height: 50vh; font-size: 5vh; line-height: 50vh; margin: 10vh auto; overflow: hidden; text-align: center; width: 50vw; } #data { background-color: rgba(255, 255, 255, .5); left: 0; padding: .5em; position: fixed; top: 0; }
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <section id="one"></section> <section id="two"></section> <section id="three"></section> <section id="four"></section> <section id="five"></section> <section id="six"></section> <div id="data">data here</div>

在玩了一會兒之后,我想我已經找到了最簡單的方法:我基本上確定了元素在視口上延伸了多少(在哪個方向上無關緊要),並基於此可以輕松計算出多少其中可見。

 // When the page is completely loaded. $(document).ready(function() { // Returns in percentages how much can be seen vertically // of an element in the current viewport. $.fn.pvisible = function() { var eTop = this.offset().top; var eBottom = eTop + this.height(); var wTop = $(window).scrollTop(); var wBottom = wTop + $(window).height(); var totalH = Math.max(eBottom, wBottom) - Math.min(eTop, wTop); var wComp = totalH - $(window).height(); var eIn = this.height() - wComp; return (eIn <= 0 ? 0 : eIn / this.height() * 100); } // If the page is scrolled. $(window).scroll(function() { // Setting the opacity of the divs. $("div").each(function() { $(this).css("opacity", Math.round($(this).pvisible()) / 100); }); }); });
 html, body { width: 100%; height: 100%; } body { background-color: rgba(255, 191, 127, 1); } div { width: 60%; height: 30%; margin: 5% auto; background-color: rgba(175, 153, 131, 1); }
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div>

一個小插圖來幫助理解它是如何工作的:

在此處輸入圖片說明

Chrome 現在支持Intersection Observer API

示例(打字稿):

export const elementVisibleInPercent = (element: HTMLElement) => {
    return new Promise((resolve, reject) => {
        const observer = new IntersectionObserver((entries: IntersectionObserverEntry[]) => {
            entries.forEach((entry: IntersectionObserverEntry) => {
                resolve(Math.floor(entry.intersectionRatio * 100));
                clearTimeout(timeout);
                observer.disconnect();
            });
        });

        observer.observe(element);
        // Probably not needed, but in case something goes wrong.
        const timeout = setTimeout(() => {
            reject();
        }, 500);
    });
};

const example = document.getElementById('example');
const percentageVisible = elementVisibleInPercent(example);

示例(JavaScript):

export const elementVisibleInPercent = (element) => {
    return new Promise((resolve, reject) => {
        const observer = new IntersectionObserver(entries => {
            entries.forEach(entry => {
                resolve(Math.floor(entry.intersectionRatio * 100));
                clearTimeout(timeout);
                observer.disconnect();
            });
        });

        observer.observe(element);
        // Probably not needed, but in case something goes wrong.
        const timeout = setTimeout(() => {
            reject();
        }, 500);
    });
};

const example = document.getElementById('example');
const percentageVisible = elementVisibleInPercent(example);

請注意, Intersection Observer API從那時起就可用,專門為此目的而制作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM