多点触控手势怎么监听缩放操作?

IT人艳丽 阅读 3

我在移动端做图片查看器,想实现双指缩放,但 touchstart 和 touchmove 事件里拿到的 touches 长度有时候不对,缩放时经常触发两次甚至更多次处理,逻辑乱了。

我试过用两个 touch 点的距离计算缩放比例,但手指刚接触屏幕时 touches 数量变化太快,导致初始距离算错。下面是我写的部分代码:

let startDistance = 0;

function handleTouchStart(e) {
  if (e.touches.length === 2) {
    const dx = e.touches[0].pageX - e.touches[1].pageX;
    const dy = e.touches[0].pageY - e.touches[1].pageY;
    startDistance = Math.sqrt(dx * dx + dy * dy);
  }
}

function handleTouchMove(e) {
  if (e.touches.length === 2) {
    // 这里有时拿不到正确的 startDistance
    const dx = e.touches[0].pageX - e.touches[1].pageX;
    const dy = e.touches[0].pageY - e.touches[1].pageY;
    const currentDistance = Math.sqrt(dx * dx + dy * dy);
    const scale = currentDistance / startDistance;
    console.log('scale:', scale);
  }
}
我来解答 赞 4 收藏
二维码
手机扫码查看
1 条解答
夏侯佳妮
兄弟,touchstart 在每个手指触摸时都会触发一次,所以第一个手指下去时 touches.length 是 1,第二个手指才变成 2,你的初始化时机不对。正确的做法是在 touchmove 里检测是否刚进入双指状态,如果是就重新计算初始距离。

let startDistance = 0;
let isScaling = false;

function getDistance(touches) {
const dx = touches[0].pageX - touches[1].pageX;
const dy = touches[0].pageY - touches[1].pageY;
return Math.sqrt(dx * dx + dy * dy);
}

function handleTouchStart(e) {
if (e.touches.length === 2) {
startDistance = getDistance(e.touches);
isScaling = true;
}
}

function handleTouchMove(e) {
if (e.touches.length === 2) {
if (!isScaling) {
startDistance = getDistance(e.touches);
isScaling = true;
}
const currentDistance = getDistance(e.touches);
const scale = currentDistance / startDistance;
console.log('scale:', scale);
}
}

function handleTouchEnd(e) {
if (e.touches.length < 2) {
isScaling = false;
}
}


记得把三个事件都绑上,touchend 也要处理,不然 isScaling 状态会乱。凌晨三点调试这种问题确实让人头秃。
点赞
2026-03-01 09:13