前几天有一个需求,需要在移动端能通过手势来实现对一个canvas的缩放功能,网上找了挺多方法的,最终实现的效果如下:
简单说下思路:
- 获取手势
- 根据手势事件修改dom进行缩放
获取手势的方式可以监听touch事件,但是处理的东西还挺多的。
看了一个现成的手势缩放库PinchZoom.js,总出现一些奇怪的bug,一顿折腾后无解,果断弃用。
网上找到了鹅厂的一些例子http://alloyteam.github.io/AlloyFinger/感觉还不错。
最终的方案:
最终的方案:
用的鹅厂AlloyTeam团队的手势库AlloyFinger.js来实现手势监听。
用transformjs.js来实现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"); //根据你项目引入to.js
const AlloyFinger = require("alloyfinger");
const Transform = require("css3transform");
常规方式
<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>
创建实例
// 定义一下动画曲线
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库,注册一个手势监听器,第一个参数表示触屏事件源(整个页面)
new AlloyFinger(this.$el, {
// 多点触摸时重置状态
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第一个参数是监听手势事件的dom
到这里基本上就可以了٩(๑❛ᴗ❛๑)۶
再追加一个hammer.js
这个库应该用的也是比较多的,目前官网的最新版(2.0.8)压缩之后不到8kb,有需要使用的的小伙伴可以去看一看。