x-previewMedia-s 图片视频混合预览
全屏预览图片与视频的混合列表,对齐微信 wx.previewMedia。横滑翻页、双击与双指缩放、下拉关闭、视频播放、长按菜单。
微信小程序直通 wx.previewMedia,其余四端全部原生自绘,不依赖 uni.previewImage(它只吃图片)。
兼容性
| Harmony | iOS | Android | Web | 小程序 |
|---|---|---|---|---|
| 支持 | 支持 | 支持 | 支持 | 支持(微信) |
调用
ts
import { previewMedia, closePreviewMedia, XPreviewMediaOptions } from "@/uni_modules/x-previewMedia-s"
previewMedia({
sources: [
{ url: "https://example.com/a.jpg" },
{ url: "https://example.com/b.mp4", type: "video", poster: "https://example.com/b.jpg" },
{ url: "/static/local.png" }
],
current: 1,
showmenu: true,
onChange: (res) => {
console.log("切到", res.index, res.type, res.url)
},
onLongPress: (res) => {
console.log("长按", res.url)
}
} as XPreviewMediaOptions)方法
| 名称 | 说明 |
|---|---|
| previewMedia | 打开全屏预览 |
| closePreviewMedia | 主动关闭当前预览,微信端不支持 |
previewMedia 的 success 表示预览层已打开,不是关闭时机;要拿关闭时机用 onClose。同一时刻只允许一个预览,重复调用返回 1005。
参数
| 字段 | 默认 | 说明 |
|---|---|---|
| sources | 必填 | 资源列表,url 为空的项直接丢弃 |
| current | 0 | 打开时停留的序号,越界会夹到合法区间 |
| showmenu | true | 长按时是否弹菜单。关掉后 onLongPress 照常触发,只是不弹层 |
| referrerPolicy | no-referrer | 拉远程资源时是否带 Referer,origin 时带资源自身 origin |
| indicator | default | default 圆点 / number 数字 / none 不显示,微信端不支持 |
| loop | false | 首尾循环滑动,微信端不支持 |
| autoplay | false | 视频切到当前页自动起播,默认与微信一致靠点击起播 |
| muted | false | 视频静音起播 |
| menuItems | 空 | 长按菜单文案与顺序,为空则长按只抛事件不弹层,微信端不支持 |
| menuItemColor | #000000 | 菜单文字颜色,iOS / Android / 鸿蒙 / Web 生效 |
sources[] 的字段:
| 字段 | 默认 | 说明 |
|---|---|---|
| url | 必填 | 图片或视频地址,支持 http(s)、file://、本地静态资源 |
| type | image | image / video,缺省按扩展名兜底 |
| poster | 空 | 视频封面,仅 type 为 video 时生效,留空用首帧 |
| liveVideo | 空 | 实况照片配对的 MOV 地址,仅 type 为 image 时生效,只有 iOS 渲染 |
type 缺省时按扩展名兜底(mp4 mov m4v 3gp mkv webm avi flv ts m3u8 判为视频),判不出当图片。
实况照片
只有 iOS 支持,走系统原生 PHLivePhotoView。url 传静图,liveVideo 传配对的 MOV:
ts
previewMedia({
sources: [
{ url: "/static/live/IMG_0001.HEIC", liveVideo: "/static/live/IMG_0001.MOV" }
]
} as XPreviewMediaOptions)交互是点右上角的 LIVE 徽标播放,徽标用的是系统 livePhotoBadgeImage。系统自带的「按住播放」手势被插件主动关掉了,否则会和长按菜单抢同一个手势;长按行为保持不变,仍然是抛 onLongPress 加弹菜单。图片放大或菜单弹着时不响应播放,切页会停掉上一页的播放。
事件
| 名称 | 触发时机 |
|---|---|
| onChange | 滑动切换资源后 |
| onLongPress | 长按发生时,早于菜单弹出 |
| onMenuTap | 菜单项被点击 |
| onLoadError | 单项资源加载失败,预览不关闭 |
| onClose | 预览关闭 |
这些事件在微信端都不触发,微信的预览界面由系统接管,拿不到内部状态。
长按菜单
菜单是纯壳子:插件负责弹出、命中、收起,不执行任何动作。文案完全由 menuItems 决定,识别码、分享、存相册各接自己已有的插件:
ts
previewMedia({
sources: [{ url: "https://example.com/qrcode.png" }],
menuItems: ["分享", "识别", "保存"],
onMenuTap: (res) => {
// res.tapIndex 与 menuItems 下标一致,res.itemText 是命中的文案
if (res.itemText == "分享") shareByMyPlugin(res.url)
if (res.itemText == "识别") scanByMyPlugin(res.url)
if (res.itemText == "保存") saveByMyPlugin(res.url)
}
} as XPreviewMediaOptions)不传 menuItems 就只有 onLongPress,适合自绘菜单;showmenu: false 也是同样效果。菜单弹着时按返回键先收菜单,再按一次才关预览。
交互
| 手势 | 行为 |
|---|---|
| 横滑 | 翻页,非循环时越界有阻尼;距离不够但甩得快也翻页 |
| 双击 | 图片在 1x 与 2x 之间切换,按落点锚定,视频不响应 |
| 双指 | 图片缩放,上限 4x,按双指中心锚定;超出 1x~4x 可跟手拉出一段,松手弹回 |
| 单指拖动 | 放大后平移画面,松手带惯性滑行;拖出边界有阻尼,松手弹回;未放大时下拉关闭 |
| 单击 | 图片关闭预览;放大状态先复位;视频切换播放 |
| 长按 | 恒抛 onLongPress,showmenu 且 menuItems 非空时弹菜单 |
| 返回 | Android 返回键、鸿蒙返回手势、Web 浏览器返回都只关预览这一层 |
错误码
| errCode | 说明 |
|---|---|
| 1001 | 系统错误,预览层创建失败 |
| 1002 | 参数错误 |
| 1003 | 资源列表为空 |
| 1005 | 正在预览中 |
| 1007 | 当前没有预览,closePreviewMedia 专用 |
| 1008 | 当前平台不支持此功能 |
| 1009 | 资源加载失败 |
| 1010 | 实况照片加载失败,已降级为静态图,仅 iOS |
更新日志
1.0.0(2026-08-27)
- 新增 previewMedia / closePreviewMedia,五端对齐微信 wx.previewMedia
- 微信小程序直通 wx.previewMedia,Android / iOS / 鸿蒙 / Web 全原生自绘
- 图片双击与双指缩放、横滑翻页、下拉关闭、视频播放
- 预览层四端都用独立窗口层:Android Dialog、iOS 独立 UIWindow、鸿蒙 openCustomDialog、Web 压 history 记录,返回只关预览不退页面
- 长按恒抛 onLongPress,菜单文案由 menuItems 传入,命中项经 onMenuTap 抛出,保存 / 分享 / 识别码全部由页面实现
- 插件不落库不分享,不申请相册、存储与分享相关权限
- Android / iOS 播控条图标用插件内独立 remixicon 副本,鸿蒙与 Web 用系统自带控制条
- sources[] 新增 liveVideo,iOS 走系统 PHLivePhotoView 渲染实况照片,点右上角 LIVE 徽标播放
- iOS 关掉系统自带的按住播放手势,避免和长按菜单抢手势;放大或菜单弹出时不响应播放
- 实况照片配对失败或下载失败退回静态图并抛 1010,其余四端忽略 liveVideo 按静图渲染
- 新增 onLoadError 事件,接出原生层的单项加载失败(含 1009 与 1010),预览不会因此关闭
- 放大后拖动松手带惯性滑行,拖出边界跟手变重、松手弹回;双指拉出 1x~4x 区间后松手同样弹回
- 横滑翻页补速度判定,距离不够但甩得快也翻页
- 四端惯性跑同一套逐帧衰减公式且参数一致,各端驱动器分别是 CADisplayLink / Choreographer / setInterval / requestAnimationFrame,滑行途中可被新触摸立即接手
- 修复鸿蒙缩放限位按页面尺寸计算的问题,改用 Image onComplete 回填的实际显示尺寸,竖屏看横图不再能把画面拖进黑边
- 修复 Web 双指缩放每帧都挂 200ms transition 导致缩放滞后手指的问题
