应接管预览链路:选图后存tempFilePaths到data,用自定义组件渲染缩略图并点击触发预览,而非直接调用uni.previewImage;需自行实现缩放、拖拽、滑动三类手势,处理H5与小程序兼容性问题,并维护图片加载状态兜底失败场景。
直接调用 uni.previewImage 会跳转到原生相册式预览页,无法控制样式、手势或加按钮。想自定义,就得自己接管「点击图片 → 打开预览层」这个链路。关键不是替换选图 API,而是拦截后续展示行为。
常见错误是:选完图就立刻把 tempFilePaths 丢给 uni.previewImage,结果完全失去控制权。正确做法是把路径存进 data,再用自定义组件渲染。
res.tempFilePaths 存入 imageList 数组(不要直接调用预览)<image> 渲染缩略图,@click="openPreview(index)" 触发自定义预览openPreview 方法里只做两件事:设置当前索引、置 previewVisible = true
props 接收 urls 和 current,不依赖 uni API 渲染用户点开一张图,预期能缩放、拖拽、滑动切图——这三者缺一不可,但 UniApp 的 <movable-view> 和 <swiper> 组合容易出问题。尤其在 H5 和小程序端表现不一致。
最容易踩的坑是:只实现双指缩放,没处理单指拖拽时缩放态下的位移;或者 swiper 切图时 movable-view 没重置 transform,导致下一张图继承上一张的偏移。
touchstart + touchmove 判断多指距离变化,更新 scale 值,同时禁用 swiper 的 touchmove 阻止冲突scale > 1 时才启用,且每次 touchend 后要记录 offsetX/offsetY,不能靠 CSS transition 过渡scale=1、offsetX=0、offsetY=0,否则手势状态残留uni-gallery
uni-gallery 确实封装了基础预览,但它把图片加载、缩放、指示器全耦合在一起,且不暴露内部 transform 控制权。你没法加下载按钮、水印、长按保存,也不能改指示器位置或动画曲线。
更实际的问题是:它默认使用 mode="widthFix" 渲染图片,遇到超长图(比如截图、文档扫描件)会严重变形;而你自己写的组件可以按需判断宽高比,动态设 mode 或加 scroll-view 包裹。
uni-gallery 足够;但凡要加「保存到相册」「复制链接」「查看原图大小」,就得自己写transform: scale() 实现,但在某些 Android 微信 WebView 下有重绘闪烁,自定义组件可用 zoom: scale() + overflow: hidden 规避position: fixed 遮罩,滚动页面时遮罩可能错位;自定义组件可改用 position: absolute + z-index 精确控制层级用户网络差、图片链接过期、CDN 返回 404,都会让预览页卡在 loading 或显示空白。官方 uni.previewImage 会自动 fallback 到占位图,但自定义组件不会。
别只靠 @error 事件——它在某些平台(如支付宝小程序)不触发,而且无法区分是加载失败还是图片本身为空。
loadStatus 数组,初始为 'loading',@load 改为 'success',@error 改为 'failed'
swiper-item 内加条件渲染:v-if="loadStatus[index] === 'success'" 显示图片,else-if 显示灰色占位 + 重试按钮