三種方法:1.利用offsetTop和scrollTop取得元素的位置,判斷是否小於等於viewPortHeight(視圖埠距離)即可。 2.利用getBoundingClientRect()判斷,語法「元素物件.getBoundingClientRect()」。 3.利用IntersectionObserver判斷,只需要檢查指定元素和視覺區域是否重疊即可。
本教學操作環境:windows7系統、vue3版,DELL G3電腦。
可視區域即我們瀏覽網頁的裝置肉眼可見的區域,如下圖
在日常開發中,我們經常需要判斷目標元素是否在視窗之內或和視窗的距離小於一個值(例如100 px),從而實現一些常用的功能,例如:
判斷一個元素是否在視覺區域,我們常用的有三種方法:
offsetTop、scrollTop
getBoundingClientRect
Intersection Observer
offsetTop
,元素的上外邊框至包含元素的上內邊框之間的像素距離,其他offset
屬性如下圖所示:
下面再來了解下方clientWidth
、clientHeight
:
##clientWidth
clientHeight
:元素內容區高度加上上下內邊距高度,即
clientHeight = content padding
這裡可以看到client
元素都不包含外邊距#最後,關於
scrollWidth 主要用於確定元素內容的實際大小
和scrollTop
屬性既可以決定元素目前捲動的狀態,也可以設定元素的捲動位置
scrollTop > 0
#水平捲動將元素的
scrollLeft設為0,可以重置元素的捲動位置
#下面再看看如何實作判斷:
公式如下:
<pre class="brush:js;toolbar:false;">el.offsetTop - document.documentElement.scrollTop <= viewPortHeight</pre>
程式碼實作:
<pre class="brush:js;toolbar:false;">function isInViewPortOfOne (el) {
// viewPortHeight 兼容所有浏览器写法
const viewPortHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
const offsetTop = el.offsetTop
const scrollTop = document.documentElement.scrollTop
const top = offsetTop - scrollTop
return top <= viewPortHeight
}</pre>
方法2:getBoundingClientRect
#傳回值是一個
DOMRect對象,擁有left, top
bottom
,x,
y, width
, 和height
屬性。 【學習影片分享:
、
web前端影片const target = document.querySelector('.target'); const clientRect = target.getBoundingClientRect(); console.log(clientRect); // { // bottom: 556.21875, // height: 393.59375, // left: 333, // right: 1017, // top: 162.625, // width: 684 // }
top
與function isInViewPort(element) { const viewWidth = window.innerWidth || document.documentElement.clientWidth; const viewHeight = window.innerHeight || document.documentElement.clientHeight; const { top, right, bottom, left, } = element.getBoundingClientRect(); return ( top >= 0 && left >= 0 && right <= viewWidth && bottom <= viewHeight ); }###
Intersection Observer
即重叠观察者,从这个命名就可以看出它用于判断两个元素是否重叠,因为不用进行事件的监听,性能方面相比getBoundingClientRect
会好很多
使用步骤主要分为两步:创建观察者和传入被观察者
创建观察者
const options = { // 表示重叠面积占被观察者的比例,从 0 - 1 取值, // 1 表示完全被包含 threshold: 1.0, root:document.querySelector('#scrollArea') // 必须是目标元素的父级元素 }; const callback = (entries, observer) => { ....} const observer = new IntersectionObserver(callback, options);
通过new IntersectionObserver
创建了观察者 observer
,传入的参数 callback
在重叠比例超过 threshold
时会被执行`
关于callback
回调函数常用属性如下:
// 上段代码中被省略的 callback const callback = function(entries, observer) { entries.forEach(entry => { entry.time; // 触发的时间 entry.rootBounds; // 根元素的位置矩形,这种情况下为视窗位置 entry.boundingClientRect; // 被观察者的位置举行 entry.intersectionRect; // 重叠区域的位置矩形 entry.intersectionRatio; // 重叠区域占被观察者面积的比例(被观察者不是矩形时也按照矩形计算) entry.target; // 被观察者 }); };
通过 observer.observe(target)
这一行代码即可简单的注册被观察者
const target = document.querySelector('.target'); observer.observe(target);
实现:创建了一个十万个节点的长列表,当节点滚入到视窗中时,背景就会从红色变为黄色
Html
结构如下:
<div class="container"></div>
css
样式如下:
.container { display: flex; flex-wrap: wrap; } .target { margin: 5px; width: 20px; height: 20px; background: red; }
往container
插入1000个元素
const $container = $(".container"); // 插入 100000 个 <div class="target"></div> function createTargets() { const htmlString = new Array(100000) .fill('<div class="target"></div>') .join(""); $container.html(htmlString); }
这里,首先使用getBoundingClientRect
方法进行判断元素是否在可视区域
function isInViewPort(element) { const viewWidth = window.innerWidth || document.documentElement.clientWidth; const viewHeight = window.innerHeight || document.documentElement.clientHeight; const { top, right, bottom, left } = element.getBoundingClientRect(); return top >= 0 && left >= 0 && right <= viewWidth && bottom <= viewHeight; }
然后开始监听scroll
事件,判断页面上哪些元素在可视区域中,如果在可视区域中则将背景颜色设置为yellow
$(window).on("scroll", () => { console.log("scroll !"); $targets.each((index, element) => { if (isInViewPort(element)) { $(element).css("background-color", "yellow"); } }); });
通过上述方式,可以看到可视区域颜色会变成黄色了,但是可以明显看到有卡顿的现象,原因在于我们绑定了scroll
事件,scroll
事件伴随了大量的计算,会造成资源方面的浪费
下面通过Intersection Observer
的形式同样实现相同的功能
首先创建一个观察者
const observer = new IntersectionObserver(getYellow, { threshold: 1.0 });
getYellow
回调函数实现对背景颜色改变,如下:
function getYellow(entries, observer) { entries.forEach(entry => { $(entry.target).css("background-color", "yellow"); }); }
最后传入观察者,即.target
元素
$targets.each((index, element) => { observer.observe(element); });
以上是vue怎麼判斷元素是否在視覺區域的詳細內容。更多資訊請關注PHP中文網其他相關文章!