微信小程序中實現手指縮放圖片

公司開發微信小程序,pm想實現以下需求:
用手指縮放圖片。其實在實現這個需求之前,並不知道,微信公衆號以及微信小程序裏面有一個原生的api就自帶這個特效,並且微信朋友圈也是用的這個api。wx.previewImage,就是它。預覽圖片。除了不能預覽開發環境的本地電腦的圖片外,你手機真機的圖片,以及http服務器上的圖片都是能夠預覽的,並且縮放功能作得很流暢。下面就說說如何用js來實現這個功能吧。
文章裏面的思路參考此文章:連接描述小程序

先上源碼,而後在逐步剖析:微信小程序

Page({
    data: {
        touch: {
            distance: 0,
            scale: 1,
            baseWidth: null,
            baseHeight: null,
            scaleWidth: null,
            scaleHeight: null
        }
    },
    touchstartCallback: function(e) {
        // 單手指縮放開始,也不作任何處理
        if(e.touches.length == 1) return
        console.log('雙手指觸發開始')
        // 注意touchstartCallback 真正代碼的開始
        // 一開始我並無這個回調函數,會出現縮小的時候有瞬間被放大過程的bug
        // 當兩根手指放上去的時候,就將distance 初始化。
        let xMove = e.touches[1].clientX - e.touches[0].clientX;
        let yMove = e.touches[1].clientY - e.touches[0].clientY;
        let distance = Math.sqrt(xMove * xMove + yMove * yMove);
        this.setData({
           'touch.distance': distance,
        })
    },
    touchmoveCallback: function(e) {
        let touch = this.data.touch
        // 單手指縮放咱們不作任何操做
        if(e.touches.length == 1) return
        console.log('雙手指運動')
        let xMove = e.touches[1].clientX - e.touches[0].clientX;
        let yMove = e.touches[1].clientY - e.touches[0].clientY;
        // 新的 ditance
        let distance = Math.sqrt(xMove * xMove + yMove * yMove);
        let distanceDiff = distance - touch.distance;
        let newScale = touch.scale + 0.005 * distanceDiff
        // 爲了防止縮放得太大,因此scale須要限制,同理最小值也是
        if(newScale >= 2) {
            newScale = 2
        }
        if(newScale <= 0.6) {
            newScale = 0.6
        }
        let scaleWidth = newScale * touch.baseWidth
        let scaleHeight = newScale * touch.baseHeight
        // 賦值 新的 => 舊的
        this.setData({
           'touch.distance': distance,
           'touch.scale': newScale,
           'touch.scaleWidth': scaleWidth,
           'touch.scaleHeight': scaleHeight,
           'touch.diff': distanceDiff
        })
    },
    bindload: function(e) {
      // bindload 這個api是<image>組件的api相似<img>的onload屬性
      this.setData({
          'touch.baseWidth': e.detail.width,
          'touch.baseHeight': e.detail.height,
          'touch.scaleWidth': e.detail.width,
          'touch.scaleHeight': e.detail.height
      })
    }
})

由於參考的別人的博文寫的,本來想大體把源碼貼出來,好本身之後做爲筆記查看,但發佈未成功,因此仍是多寫一些思路吧。
也就是說,思路是借鑑的,實際是本身操做的。
其實這個特效主要用到了touch三兄弟事件。
更主要的仍是touchmove。
首先,咱們須要得到用戶的觸摸事件。只有得到了這個事件,小程序才能得知用戶但願縮放圖片,同時肯定圖片的縮放倍數。api

咱們發現微信提供 touchmove 事件,在用戶觸摸屏幕並在屏幕上移動手指時,這個事件就會被觸發。數組

手勢動態檢測

手勢縮放的核心思想是:根據兩隻手指相對距離的變化來對圖片進行放大或縮小。所以,咱們須要知道兩隻手指相對距離的變化,才能作到良好的縮放體驗。服務器

touchmove 事件能夠實現的功能,大體能夠總結爲:微信

手指在屏幕上進行移動時,對應的組件上就會以 16 ms 一次的頻率不斷觸發 touchmove 事件;
手指離開屏幕後,則會觸發 touchend 事件。
touchmove 事件所包含的事件對象中有一個 touches 屬性,此屬性爲當前停留在屏幕中的觸摸點信息的數組。觸摸點的信息包括:ide

identifier:觸摸點的標誌符;
pageX 和 pageY:距離文檔左上角的距離;
clientX 和 clientY:距離屏幕可顯示區域左上角距離。
咱們能夠經過不斷獲取 clientX 和 clientY 數據的方式,來肯定手指在屏幕上的位置變化。函數

let xMove = e.touches[1].clientX - e.touches[0].clientX;
let yMove = e.touches[1].clientY - e.touches[0].clientY;

distance 變量即爲兩隻手指之間的距離。在 touchmove 被觸發的時候,小程序就會計算一次 distance。this

咱們爲新的 distance 變量定名爲 newDistance,相應地,舊變量定名爲 oldDistance。code

以後,咱們設定一個新的變量 distanceDiff = newDistance - oldDistance,它反映兩次 touchmove 觸發瞬間,兩根手指相對距離的變化值。

distanceDiff 爲正數時,表示兩指間距離在變大,圖片須要被放大;反之,則表明兩指間距縮小,圖片須要被縮小。

圖片動態縮放

到這裏,咱們已經能夠探測用戶的手指距離變化了。接下來,咱們須要根據用戶的手勢,肯定圖片縮放倍數,而後根據倍數縮放圖片。

首先,要肯定 distance 的變化值與圖片放大或縮小的變化率相關聯的規則。

咱們將圖片正常顯示時的尺寸定爲基準值,存放於變量 baseWidth 和 baseHeight 中。圖片須要放大的倍數設置爲變量 scale,它的初始值和最小值爲 1,最大值可根據須要來設置。

通過屢次試驗,咱們最後肯定了一個公式:

newScale = oldScale + 0.005 * distanceDiff

在每次 touchmove 被觸發後,經過探測手指距離變化而獲得的數據,來獲得圖片按比例縮放後的高寬值。

scaleWidth = scale * baseWidth;
scaleHeight = scale * baseHeight;

wxml文件對應以下,就不作解釋了:

<view class="container">
    <view bindtouchmove="touchmoveCallback" bindtouchstart="touchstartCallback">
        <image src="../../resources/pic/cat.jpg" style="width: {{ touch.scaleWidth }}px;height: {{ touch.scaleHeight }}px" bindload="bindload"></image>
    </view>
</view>

寫到這裏發現,就算小程序用不了這個js,個人ht5頁面也是能夠用的,哈哈。

相關文章
相關標籤/搜索