前幾天有一個需求,需要在移動端能通過手勢來實現(xiàn)對一個canvas的縮放功能,網(wǎng)上找了挺多方法的,最終實現(xiàn)的效果如下:

簡單說下思路:
- 獲取手勢
- 根據(jù)手勢事件修改dom進行縮放
獲取手勢的方式可以監(jiān)聽touch事件,但是處理的東西還挺多的。
看了一個現(xiàn)成的手勢縮放庫PinchZoom.js,總出現(xiàn)一些奇怪的bug,一頓折騰后無解,果斷棄用。
網(wǎng)上找到了鵝廠的一些例子http://alloyteam.github.io/AlloyFinger/感覺還不錯。
最終的方案:
最終的方案:
用的鵝廠AlloyTeam團隊的手勢庫AlloyFinger.js來實現(xiàn)手勢監(jiān)聽。
用transformjs.js來實現(xiàn)dom變換。
貼下代碼
先引入庫
webpack方式
先裝下3個庫:
npm i -D alloyfinger
npm i -D css3transform
還有一個To.js在npm里沒找到,下載http://alloyteam.github.io/AlloyFinger/asset/to.js放本地(上面demo里有)。
后面加了一個模塊導出 module.exports = To;就可以當模塊用了。
// 引入庫
const To = require("path_to/to.js"); //根據(jù)你項目引入to.js
const AlloyFinger = require("alloyfinger");
const Transform = require("css3transform");
常規(guī)方式
<script src="http://alloyteam.github.io/AlloyFinger/asset/transform.js"></script>
<script src="http://alloyteam.github.io/AlloyFinger/alloy_finger.js"></script>
<script src="http://alloyteam.github.io/AlloyFinger/asset/to.js"></script>
創(chuàng)建實例
// 定義一下動畫曲線
function ease(x) {
return Math.sqrt(1 - Math.pow(x - 1, 2));
}
// 取渲染的canvas
let target = this.$refs.zoomTargetRef.$el;
// 設置初始縮放比
var initScale = 1;
// 使用transtrom.js 庫來給canvas添加變換
Transform(target);
// 使用AlloyFinger.js庫,注冊一個手勢監(jiān)聽器,第一個參數(shù)表示觸屏事件源(整個頁面)
new AlloyFinger(this.$el, {
// 多點觸摸時重置狀態(tài)
multipointStart: function() {
To.stopAll();
initScale = target.scaleX;
},
// 旋轉
rotate: function(evt) {
target.rotateZ += evt.angle;
},
// 縮放
pinch: function(evt) {
target.scaleX = target.scaleY = initScale * evt.zoom;
},
// 觸摸結束時的動畫
multipointEnd: function() {
// 使用To.js來管理js開啟的動畫
To.stopAll();
// 最小縮放到0.5倍
if (target.scaleX < 0.5) {
new To(target, "scaleX", 0.5, 500, ease);
new To(target, "scaleY", 0.5, 500, ease);
}
// 最大2倍
if (target.scaleX > 2) {
new To(target, "scaleX", 2, 500, ease);
new To(target, "scaleY", 2, 500, ease);
}
// 取旋轉角度
var rotation = target.rotateZ % 360;
if (rotation < 0) rotation = 360 + rotation;
target.rotateZ = rotation;
// 角度回彈
if (rotation > 0 && rotation < 45) {
new To(target, "rotateZ", 0, 500, ease);
} else if (rotation >= 315) {
new To(target, "rotateZ", 360, 500, ease);
} else if (rotation >= 45 && rotation < 135) {
new To(target, "rotateZ", 90, 500, ease);
} else if (rotation >= 135 && rotation < 225) {
new To(target, "rotateZ", 180, 500, ease);
} else if (rotation >= 225 && rotation < 315) {
new To(target, "rotateZ", 270, 500, ease);
}
},
// 拖拽
pressMove: function(evt) {
target.translateX += evt.deltaX;
target.translateY += evt.deltaY;
evt.preventDefault();
}
});
上面的AlloyFinger第一個參數(shù)是監(jiān)聽手勢事件的dom
到這里基本上就可以了?(?????)?
再追加一個hammer.js
這個庫應該用的也是比較多的,目前官網(wǎng)的最新版(2.0.8)壓縮之后不到8kb,有需要使用的的小伙伴可以去看一看。