Canvas实现手势密码需手动处理坐标映射、点选判定等,因浏览器无原生组件;touchmove易漏点是因采样不均,手指滑过两点间若未落入任一点半径R内,则无法触发选中,须用欧氏距离遍历判定点。

直接用 canvas 实现手势密码是可行的,但必须手动处理触摸/鼠标坐标映射、点选判定、路径记录和防误触逻辑——浏览器不提供原生手势密码组件,所有“解锁图案”本质都是对九个点索引序列(如 [0,4,8,6])的比对。
为什么 touchmove 容易漏点或连错
移动端 touchmove 事件触发频率高,但坐标采样不均匀;手指滑过两个点之间时,若未精确落在任一圆心 R 半径内,就无法触发选中。常见表现是:划线看起来连上了,但实际只记录了起点和终点,中间点被跳过。
- 必须在
touchmove中遍历全部 9 个点,用欧氏距离公式Math.sqrt(dx*dx + dy*dy) 判定是否进入新点范围 - 加防抖:仅当新点与上一个已选点不同,且未在
selectedPoints数组中才追加 - 不要依赖
touches[0].target—— canvas 上没有子元素,target 永远是 canvas 自身
canvas 坐标怎么对齐九宫格点位
硬编码 width=350 和 height=350 会导致横竖屏错位或小屏溢出。正确做法是动态计算点间距和偏移量,确保九点始终居中、等距。
- 设画布宽高为
W、H,预留边距padding = 40,则有效绘图区为W - 2*padding×H - 2*padding - 三行三列,共 2 个横向/纵向间隔,每个间隔 =
(W - 2*padding - 6 * radius) / 2(6 个半径来自 3 个圆直径) - 第
i行第j列点坐标:x = padding + (j + 0.5) * 2 * radius + j * gap,y = padding + (i + 0.5) * 2 * radius + i * gap
如何安全比对用户手势和预设密码
不能比“图形”,只能比点序索引数组。用户划出的 [0,1,4,7] 和预存的 [0,1,4,7] 才算通过;哪怕视觉上像,只要顺序或点数不同就失败。
立即学习“前端免费学习笔记(深入)”;
- 存储密码时用数组而非字符串(避免
"0147"和"0,1,4,7"解析歧义) - 比对前先
JSON.stringify(selectedPoints) === JSON.stringify(storedPassword),简单可靠 - 允许设置最小长度(如 ≥4),防止用户只点一个点就提交
- 失败后清空路径但保留已绘点状态,方便用户重试而不重画整个图
mouse 事件和 touch 事件能共存吗
可以,但不能简单地给同一个 canvas 绑定两套事件监听器。PC 端 mousemove 触发太密,会疯狂重复判定;移动端 touch 事件又可能被浏览器默认滚动行为中断。
- 优先检测
'ontouchstart' in window,有则只启用touchstart/move/end,禁用 mouse 系列 - 必须在
touchmove回调开头加e.preventDefault(),否则 iOS Safari 会触发页面滚动 - 开发调试时可用
if (!('ontouchstart' in window)) { useMouseFallback() }模拟,但上线务必实机测试
最易被忽略的是点位坐标计算时机——必须在 resize 后重新生成点数组并清空当前路径,否则横竖屏切换后点位漂移,用户明明划对了却验证失败。



















