更新记录
1.0.0(2026-10-09) 下载此版本
首个版本:把「任意视图内容导出为图片」的能力封装成可复用的组件与工具方法。
新增
- 组件
<yolo-export>:包裹任意内容即可导出为图片- 方法:
exportImage()/saveToAlbum()/download()/toTempFilePath()/capture() - props:
file-name、pixel-ratio、background-color、skip-fonts、skip-selector、skip-local-file、lib-path、fallback-lib-path、toast - 事件:
start/success/fail
- 方法:
js_sdk/save-image.js工具:saveImageToAlbum、saveBase64Image、downloadBase64Image、readLocalImageAsDataUrl等- 截图:主库 html-to-image(SVG foreignObject,App/H5 通用),备用 html2canvas(可关闭)
- 保存相册四级兜底:隐藏 canvas 中转 → plus Bitmap → FileSystemManager → base64 直存
踩坑记录(均已内置处理)
- 鸿蒙端 renderjs 的
callMethod只传第一个参数 → 回传统一用单个对象{ data, reason, w, h } - 鸿蒙端不能用
uni.getImageInfo解析 dataURL 取尺寸(报File name too long)→ 尺寸由 renderjs 按「节点尺寸 × 倍率」回传 - 隐藏 canvas 尺寸为 0 时
drawImage抛InvalidStateError→ 占位尺寸 + 节点尺寸校验 - 安卓/iOS 的
file://下本地图片会污染画布(Tainted canvases)→ 默认跳过本地图节点,并提供readLocalImageAsDataUrl内联方案 - App 的
file://下远程图标字体必然被 CORS 拦截 →skipFonts跳过字体内嵌,减少无效请求与报错
平台兼容性
uni-app(3.8.5)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| × | √ | √ | √ | √ | × | √ | √ | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | × | × | × | × | × | - | × | × |
yolo-export 视图截图导出
把任意视图内容截成图片并导出:用 <yolo-export> 包裹要导出的内容,通过 ref 调方法即可拿到图片(base64 / 临时文件路径)、保存到相册或下载。
不绑定任何业务 —— 分享卡片、海报、报表、票据、二维码等场景都能复用。
平台支持
| 平台 | 支持 | 说明 |
|---|---|---|
| App(Android / iOS) | √ | 主路径 canvas 中转;另有 plus / FileSystemManager / base64 直存兜底 |
| App(鸿蒙) | √ | 仅 canvas 中转可用(鸿蒙无 plus、无 uni.env),插件已内置该路径 |
| H5 | √ | 直接下载 PNG |
| 小程序 | × | 未适配(渲染层与 App/H5 差异大,需要另一套 canvas 方案) |
| uni-app x | × | 未适配 |
鸿蒙端
createCanvasContext/canvasToTempFilePath需要 HBuilderX 4.23+。
快速开始
<template>
<yolo-export
ref="exporter"
file-name="share-card"
@start="saving = true"
@success="saving = false"
@fail="saving = false"
>
<!-- 这里的内容会被整块截图 -->
<view class="card">
<text>任意内容</text>
</view>
</yolo-export>
<button :loading="saving" @click="onSave">保存到相册</button>
</template>
<script setup>
import { ref } from 'vue'
import YoloExport from '@/uni_modules/yolo-export/components/yolo-export/yolo-export.vue'
const exporter = ref(null)
const saving = ref(false)
async function onSave() {
// exportImage():App 存相册 / H5 下载,最常用
await exporter.value.exportImage()
}
</script>
组件注册方式(二选一)
- 显式 import(推荐):如上,标签写
<YoloExport>或<yolo-export>,任何时候都可靠 - easycom 自动注册:符合
uni_modules/<插件id>/components/<组件名>/<组件名>.vue结构, 无需 import 即可用<yolo-export>,前提是pages.json的easycom.autoscan为true
⚠️ HBuilderX 的 easycom 组件清单在启动时扫描一次:项目运行中新增
uni_modules插件, 本次运行可能仍报Failed to resolve component: yolo-export,重启运行即可。 想省掉这类时机问题,直接用方式 1。
组件方法(通过 ref 调用)
| 方法 | 说明 | 返回 |
|---|---|---|
exportImage(options?) |
自动:App 存相册 / H5 下载 | { base64, fileName, width, height, tempFilePath?, via? } |
saveToAlbum(options?) |
App 存相册(H5 会降级为下载) | 同上 |
download(options?) |
H5 浏览器下载(App 端会降级为存相册) | 同上 |
toTempFilePath(options?) |
App:截图落成临时文件,可用于上传 | { tempFilePath, ... } |
capture(options?) |
只截图,拿 dataURL(全端) | { base64, width, height } |
options 可覆盖组件 props:{ fileName, timeout }(超时默认 15 秒)。方法均返回 Promise,失败时 reject 并带中文原因。
组件 props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
file-name |
String | export |
导出文件名(不含后缀,按图片类型自动补) |
pixel-ratio |
Number | 3 |
截图倍率,越大越清晰、体积越大(建议 1~4) |
background-color |
String | #ffffff |
截图背景色,透明区域会填充该色 |
skip-fonts |
Boolean | true |
跳过 Web 字体内嵌(远程图标字体在 App 的 file:// 下必被 CORS 拦,跳过可少一堆报错) |
skip-selector |
String | - | 截图时额外排除的节点(CSS 选择器,逗号分隔),如 .no-export |
skip-local-file |
Boolean | null |
是否跳过引用本地文件的图片节点。null = 自动:安卓/iOS 跳过,鸿蒙/H5 保留(原因见下) |
lib-path |
String | 插件内置 | 主截图库地址,一般不用改 |
fallback-lib-path |
String | 插件内置 | 备用库(html2canvas);传 none 可关闭以少加载 190KB |
toast |
Boolean | true |
是否使用内置系统提示(宿主有自己的交互时可关掉) |
组件事件
| 事件 | 参数 | 说明 |
|---|---|---|
@start |
{ mode } |
开始导出(可用来开按钮 loading) |
@success |
{ base64, fileName, tempFilePath?, via? } |
导出成功;via 记录实际走通的保存通道,便于排障 |
@fail |
{ mode, message } |
导出失败,message 为中文原因 |
工具方法(js_sdk/save-image.js)
不依赖组件,可直接 import 使用:
import {
saveImageToAlbum, // { base64 | filePath, fileName } → 相册,多通道降级
saveBase64Image, // { base64, fileName } → 本地临时文件路径
downloadBase64Image, // base64 → 浏览器下载(H5)
readLocalImageAsDataUrl, // '/static/xxx.png' → dataURL
writeBase64ToFile, // base64 → 本地文件(Android/iOS)
stripBase64Prefix, // 去掉 data:image/...;base64, 前缀
withExt, // 按 mime 补文件名后缀
hasPlus, // 当前是否具备 plus 能力
isWeb, // 当前是否 H5
} from '@/uni_modules/yolo-export/js_sdk/save-image.js'
常见问题
1. 安卓导出失败:「画布可能被图片污染 / Tainted canvases」
安卓(以及 iOS)的页面源是 file://,把本地文件图片画进 canvas 会让画布变成 tainted,导出时 toDataURL 直接抛 SecurityError。
两种处理方式:
-
推荐:导出前把本地图转成 dataURL(无跨源属性,双端都安全)
import { readLocalImageAsDataUrl } from '@/uni_modules/yolo-export/js_sdk/save-image.js' const logoSrc = ref('/static/images/logo.png') readLocalImageAsDataUrl('/static/images/logo.png') .then(uri => { if (uri) logoSrc.value = uri }) .catch(() => { /* 失败就沿用静态路径 */ })<yolo-export> <image :src="logoSrc" /> </yolo-export> -
兜底:插件默认(
skip-local-file为null)在安卓/iOS 自动跳过这类图片节点 —— 少一张图,但整张导出不会失败。鸿蒙与 H5 不受影响,本地图照常渲染。
2. 鸿蒙端导出很慢或一直转圈
鸿蒙走的是「隐藏 canvas 中转」:截图 → drawImage 到离屏 canvas → canvasToTempFilePath → 保存相册。中间会有一次系统相册授权弹窗(约数秒),属正常现象。
3. 组件内容没变却被截了旧图 / 打开就自动截图
组件内部用 shotPayload.key 自增触发 renderjs,用完即归零。若你自己 fork 了组件代码,请保留这一机制(key 不归零时,内容重建会被当成新值再截一次)。
4. 截图里图标/字体变成方框
skip-fonts 会跳过字体内嵌,远程图标字体(如 //at.alicdn.com/...)在 App 的 file:// 下本来就加载不到。如需图标出现在导出图里,建议改用图片/SVG 图标,或把字体文件下载到本地静态目录后引入。
5. 内容尺寸为 0 时导出失败
组件会先校验节点尺寸,为 0 时报「导出节点尺寸为 0,请确认内容已渲染」。常见于内容在 v-if 内尚未渲染、或父容器 display:none 时触发导出。
目录结构
yolo-export/
├─ components/yolo-export/yolo-export.vue # 导出组件(含 renderjs 截图模块)
├─ js_sdk/save-image.js # 通用图片工具(存相册/下载/本地图转 dataURL)
├─ static/js/html-to-image.js # 主截图库(19KB)
├─ static/js/html2canvas.min.js # 备用截图库(194KB,可关闭)
├─ changelog.md
└─ package.json

收藏人数:
下载插件并导入HBuilderX
赞赏(0)
下载 16
赞赏 1
下载 12663633
赞赏 1955
赞赏
京公网安备:11010802035340号