uni.previewimage是最简图片预览方案,但默认不支持手势缩放;需自行封装touch事件实现缩放拖拽,或使用原生插件提升体验。

uni-app 中 uni.previewImage 是最简方案,但默认不支持手势缩放
直接调用 uni.previewImage 能快速实现图片列表预览和左右滑动,但它在 iOS 和部分安卓 WebView 中默认禁用手势缩放(双指放大/单指拖拽),用户点开后以为“卡住了”。这不是 bug,是平台 WebView 的安全策略限制——除非页面本身启用了 viewport 缩放许可,且图片渲染在原生层之上。
实操建议:
- 确保
pages.json中对应页面的"disableScroll": false(默认即可,禁用会导致滑动失效) - 调用前检查
current是否为合法索引(字符串或数字),否则滑动会跳到第一张 - 若图片来自临时路径(如
uni.chooseImage返回的tempFilePaths),必须传数组,不能只传单图字符串 - 安卓真机上若滑动卡顿,大概率是图片尺寸过大(>2000px 宽),建议服务端返回适配预览尺寸的缩略图 URL
需要缩放?得自己封装一个基于 touchmove 的图片查看器
官方 uni.previewImage 不开放内部 canvas 或 image 元素控制权,所以缩放、旋转、长按保存等交互必须手写。核心思路是:用 <image></image> + transform: scale() translate() + 原生 touch 事件模拟手势。
关键注意点:
- 必须监听
touchstart/touchmove/touchend,不能依赖@touch(Vue 修饰符会吞掉部分事件) -
event.touches在双指操作时才有两个点,需计算两指距离变化来驱动scale,单指移动则更新translateX/Y - 缩放中心点不是屏幕中心,而是两指中点,否则放大会偏移——要用
getBoundingClientRect()动态算相对位移 - H5 端记得加
user-select: none防止长按弹出菜单干扰手势
左右滑动切换图片,别用 swiper 组件直接套图
很多开发者把多张大图塞进 <swiper></swiper>,看似能滑,实则隐患极多:内存暴涨(尤其 iOS)、滑动卡顿、图片加载错乱、current 同步失败。uni-app 的 swiper 是基于 view 层滚动,对大图资源不友好。
更稳妥的做法是:
- 只渲染当前页 + 左右各一张(共三张),用
v-if控制显隐,而非v-show(避免 DOM 积压) - 滑动结束(
@change)后再懒加载下一张图的src,用uni.getImageInfo预检宽高防重绘抖动 - 禁止用户快速连滑(加
isTransitioning锁),否则swiper的current会丢失中间态 - App 端可考虑调用原生插件(如
uni_modules/uni-image-preview),它用原生ViewPager/UIPageViewController实现,性能远超 webview
真机调试时图片空白?重点查这三处
开发时 H5 正常,但 App 或小程序里预览一片白,90% 出在这几个地方:
-
src是相对路径(如../../static/a.jpg)→ 必须转成绝对路径或网络地址,uni.previewImage不支持包内相对路径 - 图片跨域(尤其是从接口返回的 base64 或 blob URL)→ 小程序要求域名备案且配置 download 域名;App 端需在
manifest.json中勾选 “允许任意域名”(仅调试用) - HTTPS 混合内容(页面是 https,但图片地址是 http)→ 微信小程序直接拦截;App 端 Android 9+ 默认禁止 cleartext traffic,需在
android/app/src/main/AndroidManifest.xml添加android:usesCleartextTraffic="true"
缩放和滑动逻辑越靠近原生能力,体验越稳;但业务里是否值得投入手写,取决于用户是否真会放大看细节。多数场景下,先用 uni.previewImage 跑通,再根据反馈迭代更实际。











