手机图片手势缩放失效的主因是viewport禁用了user-scalable,导致ios safari屏蔽双指事件;需设user-scalable=yes、maximum-scale=5.0,用event.touches[0/1]计算欧氏距离与中点,scale累乘并动态设transformorigin。

手机上图片默认不支持手势缩放——不是你代码写错了,是浏览器根本没把双指事件交给你处理。
viewport 必须放开 user-scalable=yes
很多项目为了“防止用户乱缩放”,在 <meta name="viewport"> 里写了 user-scalable=no 或 maximum-scale=1.0。这会导致 iOS Safari 直接屏蔽所有多点触摸事件,touchstart 和 touchmove 根本不会触发。
- 正确配置示例:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, user-scalable=yes"> -
maximum-scale=5.0是安全上限,再高容易让图片缩放后完全移出视口且无法拖回 - 别用
touch-action: none粗暴封禁,它会同时干掉 pinch-zoom 和 pan,得不偿失
必须用 event.touches.length === 2 判断双指
新手常误用 event.changedTouches 或 event.targetTouches,结果双指移动时逻辑失效——因为 changedTouches 只记录本次变化的触点(比如刚按下/抬起),而双指持续滑动时它可能为空或只含 1 个点。
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
- 所有坐标、距离、中点计算,一律基于
event.touches[0]和event.touches[1] - 在
touchstart和touchmove回调开头加守卫:if (event.touches.length !== 2) return - 算两指距离必须用欧氏距离:
Math.hypot(t2.clientX - t1.clientX, t2.clientY - t1.clientY),别用Math.abs差值,横向滑动时误差极大
e.preventDefault() 只能在双指时调用
全局加 e.preventDefault() 会直接废掉页面滚动,用户连正常上下滑都做不到。
- 只在
touchmove中判断到event.touches.length === 2时才调用e.preventDefault() - 必须传
{ passive: false }给addEventListener,否则现代浏览器会忽略preventDefault - 缩放中心点要动态设为两指中点:
img.style.transformOrigin = `${midX}px ${midY}px`,否则缩放会从左上角拉扯
scale 值要累乘,不能重置
如果每次 touchmove 都用 currentDistance / startDistance 当前比值重设 scale,手指一抖就会跳变;必须基于当前 scale 叠加变化。
- 初始化:
let scale = 1,touchstart中记录startDistance -
touchmove中更新:scale *= currentDistance / lastDistance,再用Math.min(Math.max(scale, 1), 5)限幅 - 最后统一应用:
img.style.transform = `scale(${scale})`(注意不是scale3d,除非你要兼容老 Android)
最易被忽略的点:iOS 上一旦 user-scalable=no,JS 就彻底收不到双指事件——这不是兼容性问题,是系统级拦截,无绕过方案。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










