不管是小程序的原生Canvas组件还是Taro框架的Canvas组件。
他们在手势事件上还是没有太完善。
举例:
在双指缩放时,我们一定用的是小程序的Canvas手指触摸移动事件。
经过测试直接使用双指缩放,然后用单手拖动,再用双指缩放,再用单指拖动。 Canvas给您返回的touches数组会一直是2个。正常情况下单指返回1个,双指返回2个。
解决方案:
给Canvas创建一个控制器,意思就是制作一个跟Canvas一样大的View将Canvas移至其下层,View设置透明。所有事件绑定到View上,即可。
(仅限Android,IOS上View事件会被屏蔽)建议引入Web或做设备判断IOS直接使用Canvas Android用View做控制器
实例:
import React, { useEffect } from "react"
import Taro from "@tarojs/taro";
import { View, Canvas } from "@tarojs/components";
let ctx,
scale = 1,
tousX = 0,
tousY = 0,
touX = 0,
touY = 0,
touseX = 0,
touseY = 0,
clickBind = 0,
start;
const Canvase = () => {
const getDistance = (arr1, arr2) => {//计算缩放
if (arr1 && arr2) {
let x = arr2.pageX - arr1.pageX;
let y = arr2.pageY - arr1.pageY;
return (x * x) + (y * y);
}
}
const touchstartCallback = (e) => {//触摸开始
if (e.touches.length === 2) {//缩放
start = e.touches;
return
} else {//平移
touX = touseX + e.changedTouches[0].clientX;
touY = touseY + e.changedTouches[0].clientY;
return
}
}
const touchmoveCallback = (e) => {//用户开始拖动
if (e.changedTouches.length === 2) {//缩放
const now = e.changedTouches;
const now1 = getDistance(now[0], now[1]);
const now2 = getDistance(start[0], start[1]);
scale = now1 / now2;
return
} else {//平移
tousX = touX - e.changedTouches[0].clientX;
tousY = touY - e.changedTouches[0].clientY;
return
}
}
const touchEdn = (e) => {//记录平移位置
touseX = touX - e.changedTouches[0].clientX;
touseY = touY - e.changedTouches[0].clientY;
return
}
const handleTab = (e) => {//双击重置
clickBind = clickBind + 1;
if (clickBind >= 2) {
scale = 1;
tousX = 0;
tousY = 0;
touX = 0;
touY = 0;
touseX = 0;
touseY = 0;
}
setTimeout(() => {
clickBind = 0;
}, 500)
}
const draw = () => {
ctx.translate(-(tousX), -(tousY));
ctx.scale(scale, scale);
ctx.rect(50, 50, 50, 50);
ctx.setFillStyle('yellow');
ctx.fill();
ctx.draw();
}
useEffect(() => {
ctx = Taro.createCanvasContext('canvas');
setInterval(() => {
draw()
}, 100)
}, [])
return (
<View style={{ height: '20rem', position: 'relative' }}>
<Canvas style={{ height: '20rem' }} canvas-id='canvas' id="canvas"></Canvas>
<View
onClick={(e) => handleTab(e)}
onTouchStart={(e) => touchstartCallback(e)}
onTouchEnd={(e) => touchEdn(e)}
onTouchMove={(e) => touchmoveCallback(e)}
style={{
height: '20rem',
width: '100%',
background: 'transparent',
position: 'absolute',
top: 0,
border: '0.0625rem solid black'
}}
/>
</View>
)
}
export default Canvase