<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # IntersectionObserver 網頁開發時,常常需要了解某個元素是否進入了“視口”(viewport),即用戶能不能看到它。 ![](http://www.ruanyifeng.com/blogimg/asset/2016/bg2016110201.gif) 上圖的綠色方塊不斷滾動,頂部會提示它的可見性。 傳統的實現方法是,監聽到`scroll`事件后,調用目標元素(綠色方塊)的[`getBoundingClientRect()`](https://developer.mozilla.org/en/docs/Web/API/Element/getBoundingClientRect)方法,得到它對應于視口左上角的坐標,再判斷是否在視口之內。這種方法的缺點是,由于`scroll`事件密集發生,計算量很大,容易造成[性能問題](http://www.ruanyifeng.com/blog/2015/09/web-page-performance-in-depth.html)。 [IntersectionObserver API](https://wicg.github.io/IntersectionObserver/),可以自動“觀察”元素是否可見,Chrome 51+ 已經支持。由于可見(visible)的本質是,目標元素與視口產生一個交叉區,所以這個 API 叫做“交叉觀察器”(intersection oberserver)。 ## 簡介 IntersectionObserver API 的用法,簡單來說就是兩行。 ```javascript var observer = new IntersectionObserver(callback, options); observer.observe(target); ``` 上面代碼中,`IntersectionObserver`是瀏覽器原生提供的構造函數,接受兩個參數:`callback`是可見性變化時的回調函數,`option`是配置對象(該參數可選)。 `IntersectionObserver()`的返回值是一個觀察器實例。實例的`observe()`方法可以指定觀察哪個 DOM 節點。 ```javascript // 開始觀察 observer.observe(document.getElementById('example')); // 停止觀察 observer.unobserve(element); // 關閉觀察器 observer.disconnect(); ``` 上面代碼中,`observe()`的參數是一個 DOM 節點對象。如果要觀察多個節點,就要多次調用這個方法。 ```javascript observer.observe(elementA); observer.observe(elementB); ``` 注意,IntersectionObserver API 是異步的,不隨著目標元素的滾動同步觸發。規格寫明,`IntersectionObserver`的實現,應該采用`requestIdleCallback()`,即只有線程空閑下來,才會執行觀察器。這意味著,這個觀察器的優先級非常低,只在其他任務執行完,瀏覽器有了空閑才會執行。 ## IntersectionObserver.observe() IntersectionObserver 實例的`observe()`方法用來啟動對一個 DOM 元素的觀察。該方法接受兩個參數:回調函數`callback`和配置對象`options`。 ### callback 參數 目標元素的可見性變化時,就會調用觀察器的回調函數`callback`。 `callback`會觸發兩次。一次是目標元素剛剛進入視口(開始可見),另一次是完全離開視口(開始不可見)。 ```javascript var observer = new IntersectionObserver( (entries, observer) => { console.log(entries); } ); ``` 上面代碼中,回調函數采用的是[箭頭函數](http://es6.ruanyifeng.com/#docs/function#箭頭函數)的寫法。`callback`函數的參數(`entries`)是一個數組,每個成員都是一個[`IntersectionObserverEntry`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry)對象(詳見下文)。舉例來說,如果同時有兩個被觀察的對象的可見性發生變化,`entries`數組就會有兩個成員。 ### IntersectionObserverEntry 對象 `IntersectionObserverEntry`對象提供目標元素的信息,一共有六個屬性。 ```javascript { time: 3893.92, rootBounds: ClientRect { bottom: 920, height: 1024, left: 0, right: 1024, top: 0, width: 920 }, boundingClientRect: ClientRect { // ... }, intersectionRect: ClientRect { // ... }, intersectionRatio: 0.54, target: element } ``` 每個屬性的含義如下。 > - `time`:可見性發生變化的時間,是一個高精度時間戳,單位為毫秒 > - `target`:被觀察的目標元素,是一個 DOM 節點對象 > - `rootBounds`:容器元素的矩形區域的信息,`getBoundingClientRect()`方法的返回值,如果沒有容器元素(即直接相對于視口滾動),則返回`null` > - `boundingClientRect`:目標元素的矩形區域的信息 > - `intersectionRect`:目標元素與視口(或容器元素)的交叉區域的信息 > - `intersectionRatio`:目標元素的可見比例,即`intersectionRect`占`boundingClientRect`的比例,完全可見時為`1`,完全不可見時小于等于`0` ![](http://www.ruanyifeng.com/blogimg/asset/2016/bg2016110202.png) 上圖中,灰色的水平方框代表視口,深紅色的區域代表四個被觀察的目標元素。它們各自的`intersectionRatio`圖中都已經注明。 我寫了一個 [Demo](http://jsbin.com/canuze/edit?js,console,output),演示`IntersectionObserverEntry`對象。注意,這個 Demo 只能在 Chrome 51+ 運行。 ### Option 對象 `IntersectionObserver`構造函數的第二個參數是一個配置對象。它可以設置以下屬性。 **(1)threshold 屬性** `threshold`屬性決定了什么時候觸發回調函數,即元素進入視口(或者容器元素)多少比例時,執行回調函數。它是一個數組,每個成員都是一個門檻值,默認為`[0]`,即交叉比例(`intersectionRatio`)達到`0`時觸發回調函數。 如果`threshold`屬性是0.5,當元素進入視口50%時,觸發回調函數。如果值為`[0.3, 0.6]`,則當元素進入30%和60%是觸發回調函數。 ```javascript new IntersectionObserver( entries => {/* … */}, { threshold: [0, 0.25, 0.5, 0.75, 1] } ); ``` 用戶可以自定義這個數組。比如,上例的`[0, 0.25, 0.5, 0.75, 1]`就表示當目標元素 0%、25%、50%、75%、100% 可見時,會觸發回調函數。 ![](http://www.ruanyifeng.com/blogimg/asset/2016/bg2016110202.gif) **(2)root 屬性,rootMargin 屬性** `IntersectionObserver`不僅可以觀察元素相對于視口的可見性,還可以觀察元素相對于其所在容器的可見性。容器內滾動也會影響目標元素的可見性,參見本文開始時的那張示意圖。 IntersectionObserver API 支持容器內滾動。`root`屬性指定目標元素所在的容器節點。注意,容器元素必須是目標元素的祖先節點。 ```javascript var opts = { root: document.querySelector('.container'), rootMargin: '0px 0px -200px 0px' }; var observer = new IntersectionObserver( callback, opts ); ``` 上面代碼中,除了`root`屬性,還有[`rootMargin`](https://wicg.github.io/IntersectionObserver/#dom-intersectionobserverinit-rootmargin)屬性。該屬性用來擴展或縮小`rootBounds`這個矩形的大小,從而影響`intersectionRect`交叉區域的大小。它的寫法類似于 CSS 的`margin`屬性,比如`0px 0px 0px 0px`,依次表示 top、right、bottom 和 left 四個方向的值。 上例的`0px 0px -200px 0px`,表示容器的下邊緣向上收縮200像素,導致頁面向下滾動時,目標元素的頂部進入可視區域200像素以后,才會觸發回調函數。 這樣設置以后,不管是窗口滾動或者容器內滾動,只要目標元素可見性變化,都會觸發觀察器。 ## 實例 ### 惰性加載(lazy load) 有時,我們希望某些靜態資源(比如圖片),只有用戶向下滾動,它們進入視口時才加載,這樣可以節省帶寬,提高網頁性能。這就叫做“惰性加載”。 有了 IntersectionObserver API,實現起來就很容易了。圖像的 HTML 代碼可以寫成下面這樣。 ```html <img src="placeholder.png" data-src="img-1.jpg"> <img src="placeholder.png" data-src="img-2.jpg"> <img src="placeholder.png" data-src="img-3.jpg"> ``` 上面代碼中,圖像默認顯示一個占位符,`data-src`屬性是惰性加載的真正圖像。 ```javascript function query(selector) { return Array.from(document.querySelectorAll(selector)); } var observer = new IntersectionObserver( function(entries) { entries.forEach(function(entry) { entry.target.src = entry.target.dataset.src; observer.unobserve(entry.target); }); } ); query('.lazy-loaded').forEach(function (item) { observer.observe(item); }); ``` 上面代碼中,只有圖像開始可見時,才會加載真正的圖像文件。 ### 無限滾動 無限滾動(infinite scroll)指的是,隨著網頁滾動到底部,不斷加載新的內容到頁面,它的實現也很簡單。 ```javascript var intersectionObserver = new IntersectionObserver( function (entries) { // 如果不可見,就返回 if (entries[0].intersectionRatio <= 0) return; loadItems(10); console.log('Loaded new items'); } ); // 開始觀察 intersectionObserver.observe( document.querySelector('.scrollerFooter') ); ``` 無限滾動時,最好像上例那樣,頁面底部有一個頁尾欄(又稱[sentinels](sentinels),上例是`.scrollerFooter`)。一旦頁尾欄可見,就表示用戶到達了頁面底部,從而加載新的條目放在頁尾欄前面。否則就需要每一次頁面加入新內容時,都調用`observe()`方法,對新增內容的底部建立觀察。 ### 視頻自動播放 下面是一個視頻元素,希望它完全進入視口的時候自動播放,離開視口的時候自動暫停。 ```html <video src="foo.mp4" controls=""></video> ``` 下面是 JS 代碼。 ```javascript let video = document.querySelector('video'); let isPaused = false; let observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.intersectionRatio != 1 && !video.paused) { video.pause(); isPaused = true; } else if (isPaused) { video.play(); isPaused=false; } }); }, {threshold: 1}); observer.observe(video); ``` 上面代碼中,`IntersectionObserver()`的第二個參數是配置對象,它的`threshold`屬性等于`1`,即目標元素完全可見時觸發回調函數。 ## 參考鏈接 - [IntersectionObserver’s Coming into View](https://developers.google.com/web/updates/2016/04/intersectionobserver) - [Intersection Observers Explained](https://github.com/WICG/IntersectionObserver/blob/gh-pages/explainer.md) - [A Few Functional Uses for Intersection Observer to Know When an Element is in View](https://css-tricks.com/a-few-functional-uses-for-intersection-observer-to-know-when-an-element-is-in-view/), Preethi
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看