1. 程式人生 > >微信小程式開發筆記4—— IntersectionObserver 用法詳解

微信小程式開發筆記4—— IntersectionObserver 用法詳解

看微信文件時看到這個很有趣的api,但是官方的文件和例子關於這個api的介紹都是很讓人失望的,所以花了點時間瞭解了以下這個方法,做個記錄,供參考。

簡介

首先,我的理解是,這是一個觀察器(廢話),它用來監測目標物件與某個參照物的相交情況。什麼是相交情況?通俗的說,就是兩個區域有重疊(公共區域)了,類似與數學中的交集,不過這個是平面上的。
我們用官方給的一個簡單的例子進行講解:https://developers.weixin.qq.com/miniprogram/dev/api/wxml/wx.createIntersectionObserver.html ,點選最後的在開發者工具中預覽即可。
演示圖:
observer


可以大致的看到,當小球出現/消失的時候,頂部的文字會跟著改變,右邊的控制檯也在列印著一些東西。下面我們就根據程式碼,來一談究竟。

程式碼分析

首先是頁面

<view class="container">
  <view class="page-body">
    <view class="page-section message">
      <text wx:if="{{appear}}">
        小球出現
      </text>
      <text wx:else>
        小球消失
      </
text
>
</view> <view class="page-section"> <scroll-view class="scroll-view" scroll-y> <view class="scroll-area" style="{{appear ? 'background: #ccc' : ''}}"> <text class="notice">向下滾動讓小球出現</text> <view class="filling">
</view> <view class="ball"></view> </view> </scroll-view> </view> </view> </view>

可以看到,在scroll-view中,定義了一個樣式類為scroll-area的區域,在這裡面,又有三個子元素。分別是我們對應看到的文字(class=“notice”),和一個空白的佔位元素(class=“filling”)和小球(class=“ball”)。

頁面的樣式wxss

.scroll-view {
  height: 400rpx;
  background: #fff;
  border: 1px solid #ccc;
  box-sizing: border-box;
}

.scroll-area {
  height: 1300rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
  transition: .5s;
}

.notice {
  margin-top: 150rpx;
}

.ball {
  width: 200rpx;
  height: 200rpx;
  background: #1AAD19;
  border-radius: 50%;
}

.filling {
  height: 400rpx;
}

.message {
  width: 100%;
  display: flex;
  justify-content: center;
}

.message text {
  font-size: 40rpx;
  font-family: -apple-system-font, Helvetica Neue,Helvetica,sans-serif;
}

通過樣式檔案,我們可以看到,整個scroll-view元件,佔據螢幕高度是400rpx,但是其中的class=“scroll-area”的元素,高度是1300rpx,也就是說,內部是可以上下滾動的。畫了一張scroll-view的內部細節圖,供參考:
內部細節圖

js邏輯

Page({
  data: {
    appear: false
  },
  onLoad() {
    this._observer = wx.createIntersectionObserver(this)
    this._observer
      .relativeTo('.scroll-view')
      .observe('.ball', (res) => {
        console.log(res);
        this.setData({
          appear: res.intersectionRatio > 0
        })
      })
  },
  onUnload() {
    if (this._observer) this._observer.disconnect()
  }
})

分析

可以看到,這個觀察器是在監聽小球與最外層的scroll-view的相交情況。我們來看一下第一次相交的時候,日誌列印的結果:
日誌1

結果分析:

  1. boundingClientRect:目標邊界。這個目標,就是我們的觀察物件,可以看到剛開始相交的時候,它的位置情況。這個位置是相對於整個頁面的,不是相對於參照元素的。top = 251(px) = scroll-view的高度(200px) + "小球消失/出現"message的高度(52px) - 相交高度(1px)
  2. dataset: 觀察物件攜帶的資料。
  3. id:觀察物件的id,它與上面的dataset多使用於一次觀察多個物件的場景,用於區分不同的物件。
  4. intersectionRatio 相交比例:大於0的話表示兩者有了交集,等於1的話表示兩者已經完全相交。
  5. intersectionRect 相交區域: 可以看出此時只有1px的高度有交集
  6. relativeRect:參照區域的邊界。通過其上下左右四個屬性值可以看出它就是scroll-view元件在頁面中的位置。
  7. time: 監測到兩者相交時的時間戳,不太有用。

對應圖解可以參考:
圖解1

再看一下,從相交到沒有交集,打印出來的結果:
日誌2

結果分析:

  1. boundingClientRect:目標邊界。此時top=-48,bottom=52, 這個bottom的位置,剛好是“小球消失/出現”這個文字的所佔高度52px。所以此時是剛好看不到小球。
  2. dataset: 觀察物件攜帶的資料。
  3. id:觀察物件的id,它與上面的dataset多使用於一次觀察多個物件的場景,用於區分不同的物件。
  4. intersectionRatio 相交比例為0,說明兩者不相交。
  5. intersectionRect 相交區域。height = 0 說明 此時沒有相交了。
  6. relativeRect:參照區域的邊界。作為參考物,它的值一般是不會變的。可以對比它於開始相交時一直沒變,因為它就是一個scroll-view的元件在頁面上呈現出的位置資訊。
  7. time: 監測到兩者相交時的時間戳,不太有用。
    參考圖解:
    圖解2
    注意,上面兩個圖解中的黃色透明部分,是我們頁面上可見的區域,不要弄混了
    關於另一個api:relativeToViewport ,用法基本於這個相同,但是它相對的參照物是頁面顯示區域。

以上就是內容,全是我自己的通過程式碼和例子進行的理解,如果有不對或者不完善的地方,歡迎交流。謝謝。