摘要:公司開發(fā)微信小程序,想實(shí)現(xiàn)如下需求用手指縮放圖片。我們發(fā)現(xiàn)微信提供事件,在用戶觸摸屏幕并在屏幕上移動(dòng)手指時(shí),這個(gè)事件就會(huì)被觸發(fā)。
公司開發(fā)微信小程序,pm想實(shí)現(xiàn)如下需求:
用手指縮放圖片。其實(shí)在實(shí)現(xiàn)這個(gè)需求以前,并不知道,微信公眾號(hào)以及微信小程序里面有一個(gè)原生的api就自帶這個(gè)特效,而且微信朋友圈也是用的這個(gè)api。wx.previewImage,就是它。預(yù)覽圖片。除了不能預(yù)覽開發(fā)環(huán)境的本地電腦的圖片外,你手機(jī)真機(jī)的圖片,以及http服務(wù)器上的圖片都是可以預(yù)覽的,而且縮放功能做得很流暢。下面就說說如何用js來實(shí)現(xiàn)這個(gè)功能吧。
文章里面的思路參考此文章:鏈接描述
先上源碼,然后在逐步剖析:
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("雙手指觸發(fā)開始") // 注意touchstartCallback 真正代碼的開始 // 一開始我并沒有這個(gè)回調(diào)函數(shù),會(huì)出現(xiàn)縮小的時(shí)候有瞬間被放大過程的bug // 當(dāng)兩根手指放上去的時(shí)候,就將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("雙手指運(yùn)動(dòng)") 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 這個(gè)api是組件的api類似的onload屬性 this.setData({ "touch.baseWidth": e.detail.width, "touch.baseHeight": e.detail.height, "touch.scaleWidth": e.detail.width, "touch.scaleHeight": e.detail.height }) } })
因?yàn)閰⒖嫉膭e人的博文寫的,原本想大致把源碼貼出來,好自己以后作為筆記查看,但發(fā)布未成功,所以還是多寫一些思路吧。
也就是說,思路是借鑒的,實(shí)際是自己操作的。
其實(shí)這個(gè)特效主要用到了touch三兄弟事件。
更主要的還是touchmove。
首先,我們需要獲得用戶的觸摸事件。只有獲得了這個(gè)事件,小程序才能得知用戶希望縮放圖片,同時(shí)確定圖片的縮放倍數(shù)。
我們發(fā)現(xiàn)微信提供 touchmove 事件,在用戶觸摸屏幕并在屏幕上移動(dòng)手指時(shí),這個(gè)事件就會(huì)被觸發(fā)。
手勢(shì)動(dòng)態(tài)檢測(cè)手勢(shì)縮放的核心思想是:根據(jù)兩只手指相對(duì)距離的變化來對(duì)圖片進(jìn)行放大或縮小。因此,我們需要知道兩只手指相對(duì)距離的變化,才能做到良好的縮放體驗(yàn)。
touchmove 事件可以實(shí)現(xiàn)的功能,大致可以總結(jié)為:
手指在屏幕上進(jìn)行移動(dòng)時(shí),對(duì)應(yīng)的組件上就會(huì)以 16 ms 一次的頻率不斷觸發(fā) touchmove 事件;
手指離開屏幕后,則會(huì)觸發(fā) touchend 事件。
touchmove 事件所包含的事件對(duì)象中有一個(gè) touches 屬性,此屬性為當(dāng)前停留在屏幕中的觸摸點(diǎn)信息的數(shù)組。觸摸點(diǎn)的信息包括:
identifier:觸摸點(diǎn)的標(biāo)志符;
pageX 和 pageY:距離文檔左上角的距離;
clientX 和 clientY:距離屏幕可顯示區(qū)域左上角距離。
我們可以通過不斷獲取 clientX 和 clientY 數(shù)據(jù)的方式,來確定手指在屏幕上的位置變化。
let xMove = e.touches[1].clientX - e.touches[0].clientX; let yMove = e.touches[1].clientY - e.touches[0].clientY;
distance 變量即為兩只手指之間的距離。在 touchmove 被觸發(fā)的時(shí)候,小程序就會(huì)計(jì)算一次 distance。
我們?yōu)樾碌?distance 變量定名為 newDistance,相應(yīng)地,舊變量定名為 oldDistance。
之后,我們?cè)O(shè)定一個(gè)新的變量 distanceDiff = newDistance - oldDistance,它反映兩次 touchmove 觸發(fā)瞬間,兩根手指相對(duì)距離的變化值。
distanceDiff 為正數(shù)時(shí),表示兩指間距離在變大,圖片需要被放大;反之,則代表兩指間距縮小,圖片需要被縮小。
圖片動(dòng)態(tài)縮放到這里,我們已經(jīng)可以探測(cè)用戶的手指距離變化了。接下來,我們需要根據(jù)用戶的手勢(shì),確定圖片縮放倍數(shù),然后根據(jù)倍數(shù)縮放圖片。
首先,要確定 distance 的變化值與圖片放大或縮小的變化率相關(guān)聯(lián)的規(guī)則。
我們將圖片正常顯示時(shí)的尺寸定為基準(zhǔn)值,存放于變量 baseWidth 和 baseHeight 中。圖片需要放大的倍數(shù)設(shè)置為變量 scale,它的初始值和最小值為 1,最大值可根據(jù)需要來設(shè)置。
經(jīng)過多次試驗(yàn),我們最后確定了一個(gè)公式:
newScale = oldScale + 0.005 * distanceDiff
在每次 touchmove 被觸發(fā)后,通過探測(cè)手指距離變化而得到的數(shù)據(jù),來得到圖片按比例縮放后的高寬值。
scaleWidth = scale * baseWidth; scaleHeight = scale * baseHeight;
wxml文件對(duì)應(yīng)如下,就不做解釋了:
寫到這里發(fā)現(xiàn),就算小程序用不了這個(gè)js,我的ht5頁面也是可以用的,哈哈。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/93392.html
摘要:具體調(diào)用參考接口請(qǐng)求封裝函數(shù)一般在中實(shí)現(xiàn)微信自帶的網(wǎng)絡(luò)請(qǐng)求方法調(diào)用接口請(qǐng)求函數(shù)如在中首先需要獲取應(yīng)用實(shí)例調(diào)用數(shù)據(jù)請(qǐng)求在函數(shù)中聲明的一個(gè)全局變量,接下來使用點(diǎn)語法直接調(diào)用請(qǐng)求下來的值就可以了。 如何向微信小程序?qū)隓EMO源碼: 參考方法 參考學(xué)習(xí)小程序官方文檔 小程序官方文檔 小程序目錄簡介 app.json :設(shè)置一些工程全局的量.js : 寫一些函數(shù)邏輯.wxml: 調(diào)用.js中寫...
摘要:具體調(diào)用參考接口請(qǐng)求封裝函數(shù)一般在中實(shí)現(xiàn)微信自帶的網(wǎng)絡(luò)請(qǐng)求方法調(diào)用接口請(qǐng)求函數(shù)如在中首先需要獲取應(yīng)用實(shí)例調(diào)用數(shù)據(jù)請(qǐng)求在函數(shù)中聲明的一個(gè)全局變量,接下來使用點(diǎn)語法直接調(diào)用請(qǐng)求下來的值就可以了。 如何向微信小程序?qū)隓EMO源碼: 參考方法 參考學(xué)習(xí)小程序官方文檔 小程序官方文檔 小程序目錄簡介 app.json :設(shè)置一些工程全局的量.js : 寫一些函數(shù)邏輯.wxml: 調(diào)用.js中寫...
摘要:具體調(diào)用參考接口請(qǐng)求封裝函數(shù)一般在中實(shí)現(xiàn)微信自帶的網(wǎng)絡(luò)請(qǐng)求方法調(diào)用接口請(qǐng)求函數(shù)如在中首先需要獲取應(yīng)用實(shí)例調(diào)用數(shù)據(jù)請(qǐng)求在函數(shù)中聲明的一個(gè)全局變量,接下來使用點(diǎn)語法直接調(diào)用請(qǐng)求下來的值就可以了。 如何向微信小程序?qū)隓EMO源碼: 參考方法 參考學(xué)習(xí)小程序官方文檔 小程序官方文檔 小程序目錄簡介 app.json :設(shè)置一些工程全局的量.js : 寫一些函數(shù)邏輯.wxml: 調(diào)用.js中寫...
摘要:在開發(fā)之前你要有微信開發(fā)者工具。同時(shí)為了更適合開發(fā)微信小程序,還對(duì)進(jìn)行了擴(kuò)充以及修改,直接幫我們把適配的一部分工作都做了,比如他的,可以根據(jù)屏幕寬度進(jìn)行自適應(yīng),規(guī)定屏幕寬為。 本文由云+社區(qū)發(fā)表 這段時(shí)間有幸加入了一個(gè)關(guān)于微信小程序的項(xiàng)目開發(fā)組,從無到有的根據(jù)文檔自行學(xué)習(xí)了小程序的開發(fā)過程,前面已經(jīng)有幾位前輩的文章珠玉在前,我這里就先從前端界面的開發(fā)方面談一談小程序以及我所遇到的問題吧...
閱讀 2499·2021-11-25 09:43
閱讀 2609·2021-11-16 11:50
閱讀 3290·2021-10-09 09:44
閱讀 3201·2021-09-26 09:55
閱讀 2839·2019-08-30 13:50
閱讀 1031·2019-08-29 13:24
閱讀 2076·2019-08-26 11:44
閱讀 2802·2019-08-26 11:37