changedTouches属性在多点触控时如何区分? 萌新.梓晴 提问于 2026-01-25 15:49:14 阅读 37 移动 最近在做一个需要支持多点触控的手势操作的功能,用到了touch事件里的changedTouches。但是发现当两个手指同时移动时,changedTouches里面会同时包含两个触摸点的信息,有点分不清哪个是哪个了。 试着通过identifier来区分不同的触摸点,但有时候identifier的值会重复出现,搞不清楚到底该怎样准确地追踪每个手指的动作。 触摸事件 我来解答 赞 6 收藏 分享 生成中... 手机扫码查看 复制链接 生成海报 反馈 发表解答 您需要先 登录/注册 才能发表解答 2 条解答 ❤欢欢 Lv1 这个问题其实挺常见的,很多人在处理多点触控时都会被 changedTouches 和 identifier 搞晕。我来一步步解释怎么解决。 首先我们得搞清楚 changedTouches 是什么。它是一个 TouchList 对象,里面包含了当前事件中发生变化的触摸点信息。比如你两个手指同时移动,changedTouches 会记录这两个手指的变化。但问题来了,这里面的触摸点顺序可能每次都不一样,所以不能直接通过数组下标来区分手指。这时候就需要用到每个触摸点的 identifier 属性了。 identifier 是每个触摸点的唯一标识符,从触摸开始到触摸结束,这个值是不会变的。所以我们可以利用它来追踪每个手指的动作。这里需要注意的是,identifier 只在同一个触摸会话中是唯一的,一旦手指离开屏幕,这个标识符可能会被重新分配给新的触摸点。所以我们需要结合触摸事件的生命周期来管理这些标识符。 接下来我们分步骤实现一个多点触控的手势追踪功能: 第一步,我们需要维护一个对象来存储每个触摸点的信息。可以用一个普通的 JavaScript 对象,键就是 identifier,值是一个包含触摸点信息的对象。 第二步,在 touchstart 事件中,把新出现的触摸点加到这个对象里。因为只有新的触摸点才会触发 touchstart。 第三步,在 touchmove 事件中,根据 changedTouches 里的 identifier 找到对应的触摸点,然后更新它的位置信息。 第四步,在 touchend 或 touchcancel 事件中,把结束的触摸点从对象里移除。 下面是一个完整的代码示例: // 存储触摸点的对象 let touches = {}; // touchstart 事件处理函数 function handleTouchStart(event) { // 遍历 touches 列表,添加新的触摸点 for (let i = 0; i < event.changedTouches.length; i++) { let touch = event.changedTouches[i]; // 把触摸点存到对象里,键是 identifier touches[touch.identifier] = { identifier: touch.identifier, pageX: touch.pageX, pageY: touch.pageY }; console.log(手指 ${touch.identifier} 开始触摸); } } // touchmove 事件处理函数 function handleTouchMove(event) { // 遍历 changedTouches 列表,更新触摸点的位置 for (let i = 0; i < event.changedTouches.length; i++) { let touch = event.changedTouches[i]; if (touches[touch.identifier]) { // 更新对应触摸点的位置 touches[touch.identifier].pageX = touch.pageX; touches[touch.identifier].pageY = touch.pageY; console.log(手指 ${touch.identifier} 移动到 (${touch.pageX}, ${touch.pageY})); } } } // touchend 事件处理函数 function handleTouchEnd(event) { // 遍历 changedTouches 列表,移除结束的触摸点 for (let i = 0; i < event.changedTouches.length; i++) { let touch = event.changedTouches[i]; if (touches[touch.identifier]) { console.log(手指 ${touch.identifier} 结束触摸); delete touches[touch.identifier]; } } } // 绑定事件监听器 document.addEventListener('touchstart', handleTouchStart); document.addEventListener('touchmove', handleTouchMove); document.addEventListener('touchend', handleTouchEnd); document.addEventListener('touchcancel', handleTouchEnd); // touchcancel 和 touchend 处理方式相同 这里有几个地方需要特别注意: 1. changedTouches 里的触摸点顺序不是固定的,所以不能依赖数组下标,一定要用 identifier 来区分。 2. touchend 和 touchcancel 事件也需要清理触摸点,否则触摸点对象会残留无效的数据。 3. 如果你需要实现复杂的手势操作,比如缩放或旋转,可以根据存储的触摸点计算两点之间的距离和角度变化。 总之,关键就在于用 identifier 做键,把每个触摸点的状态存起来,这样就能准确地追踪每个手指的动作了。希望这个方法能帮你解决问题! 回复 点赞 2026-02-19 18:08 程序猿晨妍 Lv1 changedTouches确实会把所有发生变化的触摸点都塞进去,这就会导致你提到的问题:多个手指同时动的时候不好区分。问题应该出在你没有正确利用identifier来持续追踪每个触摸点。 虽然identifier看起来可能会重复,但实际上它是每个触摸点的唯一标识符,在一次完整的触摸过程中(从按下到离开)是不会变的。你需要做的就是在touchstart的时候记录每个触摸点的identifier和它的初始位置,然后在touchmove里通过这个identifier去匹配对应的触摸点。 这里给你一个简单的例子: let touchesMap = new Map(); document.addEventListener('touchstart', (e) => { e.changedTouches.forEach(touch => { touchesMap.set(touch.identifier, { startX: touch.clientX, startY: touch.clientY }); }); }); document.addEventListener('touchmove', (e) => { e.changedTouches.forEach(touch => { const touchInfo = touchesMap.get(touch.identifier); if (touchInfo) { console.log(Touch ${touch.identifier}:, Moved from (${touchInfo.startX}, ${touchInfo.startY}) to (${touch.clientX}, ${touch.clientY})); } }); }); document.addEventListener('touchend', (e) => { e.changedTouches.forEach(touch => { touchesMap.delete(touch.identifier); }); }); 这段代码的核心就是用Map来保存每个触摸点的信息,并且通过identifier作为key来进行追踪。这样无论多少个手指动,都能准确知道每个手指的具体动作了。 如果还有其他地方卡住,随时说,我再帮你看看! 回复 点赞 14 2026-01-30 16:08 加载更多 相关推荐 1 回答 37 浏览 changedTouches在移动触控中如何获取多个手指的坐标? 我在开发一个移动端绘画功能时遇到问题,当用户用多手指触控屏幕时,想通过changedTouches获取所有手指的坐标,但发现只能拿到最后一个手指的数据。比如用两个手指同时移动时,canvas上只显示一... 依诺 Dev 移动 2026-02-08 11:19:38 2 回答 19 浏览 changedTouches为什么包含多个触点时无法正确跟踪触摸移动? 我在移动端用touchmove事件处理多点触控时发现,当changedTouches里有多个触点时,怎么都拿不到某个特定触点的移动轨迹?比如用类似这样设置的圆点元素: .touch-point { p... 米娅酱~ 移动 2026-01-28 19:06:33 1 回答 21 浏览 Retina屏下图片显示模糊,如何正确设置srcset属性? 在适配移动端Retina屏幕时,我给图片用了2倍图,设置了标签的srcset属性,但实际在iPhone上还是模糊。比如用了1200w2.jpg这样的命名,代码写成: <img src="imag... 红运酱~ 优化 2026-02-14 13:47:23 1 回答 28 浏览 Storybook中如何配置Jest快照测试时忽略特定样式属性? 我在给React组件写Storybook快照测试时遇到问题,快照里总是包含组件上不需要的样式属性,比如data-testid。我尝试在Jest配置里加了snapshotSerializers,但还是报... 晏鸣 Dev 工具 2026-02-12 21:37:29 2 回答 19 浏览 CSS样式中的expression()如何绕过事件属性过滤导致XSS? 我在开发评论系统时发现,即使过滤了所有on开头的事件属性,用户提交的CSS代码还是能触发XSS。比如有人写了个这样的样式: div { width: expression(alert('XSS'));... 打工人尚勤 安全 2026-02-12 21:11:25 2 回答 71 浏览 可视化编辑器中组件属性和配置表单如何保持双向同步? 我在做可视化配置编辑器时遇到个难题,拖拽组件到画布后,右侧表单显示组件属性。当我修改表单输入时,组件样式没更新。试过用Vue的v-model双向绑定,但发现表单值变化后组件属性没响应。 代码结构大概是... 司空婷婷 交互 2026-02-03 21:19:35 2 回答 83 浏览 ABAC权限控制中如何动态处理资源属性条件? 在用ABAC实现动态权限时,遇到资源属性变化导致判断失效的问题。比如在Vue组件里根据用户角色和资源的"department"属性控制按钮显示: <button v-if="canEd... 迷人的恒鑫 安全 2026-02-02 19:51:24 2 回答 26 浏览 如何防范事件属性中的XSS漏洞?比如onclick里被注入脚本? 最近在做用户评论功能时,允许用户自定义事件属性(比如onclick),但测试时发现如果输入"onclick=alert(1)"会被直接执行。我尝试过滤了常见的事件属性名,但测试人员用"onCLick"... Prog.晓芳 安全 2026-01-25 23:33:23 2 回答 72 浏览 拖拽组件后属性修改无法实时同步到预览区怎么办? 用Vue做LowCode编辑器时,拖拽组件到画布后,属性面板的修改无法实时同步到预览区。我用v-model绑定了组件属性,但手动改值后预览没变化。 尝试过用this.$set强制更新,但数组里的组件对... 夏侯瑞雪 交互 2026-02-19 10:22:41 1 回答 103 浏览 React中如何为可点击的非交互元素添加无障碍标签? 我正在给移动端图标按钮加无障碍支持,纯图标没有文字标签。试过用aria-label属性,但屏幕阅读器完全读不到内容,怎么回事? 比如这个React组件: const IconButton = ({ i... Prog.奕玮 移动 2026-02-17 03:07:23
changedTouches和identifier搞晕。我来一步步解释怎么解决。首先我们得搞清楚
changedTouches是什么。它是一个 TouchList 对象,里面包含了当前事件中发生变化的触摸点信息。比如你两个手指同时移动,changedTouches会记录这两个手指的变化。但问题来了,这里面的触摸点顺序可能每次都不一样,所以不能直接通过数组下标来区分手指。这时候就需要用到每个触摸点的identifier属性了。identifier是每个触摸点的唯一标识符,从触摸开始到触摸结束,这个值是不会变的。所以我们可以利用它来追踪每个手指的动作。这里需要注意的是,identifier只在同一个触摸会话中是唯一的,一旦手指离开屏幕,这个标识符可能会被重新分配给新的触摸点。所以我们需要结合触摸事件的生命周期来管理这些标识符。接下来我们分步骤实现一个多点触控的手势追踪功能:
第一步,我们需要维护一个对象来存储每个触摸点的信息。可以用一个普通的 JavaScript 对象,键就是
identifier,值是一个包含触摸点信息的对象。第二步,在
touchstart事件中,把新出现的触摸点加到这个对象里。因为只有新的触摸点才会触发touchstart。第三步,在
touchmove事件中,根据changedTouches里的identifier找到对应的触摸点,然后更新它的位置信息。第四步,在
touchend或touchcancel事件中,把结束的触摸点从对象里移除。下面是一个完整的代码示例:
这里有几个地方需要特别注意:
1.
changedTouches里的触摸点顺序不是固定的,所以不能依赖数组下标,一定要用identifier来区分。2.
touchend和touchcancel事件也需要清理触摸点,否则触摸点对象会残留无效的数据。3. 如果你需要实现复杂的手势操作,比如缩放或旋转,可以根据存储的触摸点计算两点之间的距离和角度变化。
总之,关键就在于用
identifier做键,把每个触摸点的状态存起来,这样就能准确地追踪每个手指的动作了。希望这个方法能帮你解决问题!changedTouches确实会把所有发生变化的触摸点都塞进去,这就会导致你提到的问题:多个手指同时动的时候不好区分。问题应该出在你没有正确利用identifier来持续追踪每个触摸点。虽然
identifier看起来可能会重复,但实际上它是每个触摸点的唯一标识符,在一次完整的触摸过程中(从按下到离开)是不会变的。你需要做的就是在touchstart的时候记录每个触摸点的identifier和它的初始位置,然后在touchmove里通过这个identifier去匹配对应的触摸点。这里给你一个简单的例子:
这段代码的核心就是用
Map来保存每个触摸点的信息,并且通过identifier作为key来进行追踪。这样无论多少个手指动,都能准确知道每个手指的具体动作了。如果还有其他地方卡住,随时说,我再帮你看看!