场景:在Taro开发中,在商品/职位/文章的详情页需要转发生成一个png海报,如果在Web开发中,直接html+css写海报样式,Vue/Teact中通过Props传入详情信息就可以,然后定位到屏幕视口外,通过html2canvas生成和导出海报样式,但是在小程序中,无法使用html2canvas
尝试寻找第三方库
wxml2canvas/taro-wxml2canvas可以吗,我使用过,证明是不可行的,且不说taro导入第三方原生组件十分麻烦,在Taro4中,和Taro3,Taro2基本经历过多次更新,wxml2canvas/taro-wxml2canvas库已经很久没有维护,实测不可行。
taro-plugin-canvas和taro3-canvas之类的库长时间不更新无法使用;
taro-html-parser和wxParse库也是长时间不更新无法使用;
mp-html这个还在维护库只支持uniapp和原生小程序;
似乎Taro被市场抛弃了,一个纯前端解决生成分享海报的库都没有吗?
尝试Canvas绘制
其实海报就是一个png图片,canvas一样可以绘制,Taro是支持canvas的,但canvas绘制的海报在多文字处理上非常麻烦,样式调整费劲,其实先写html,让AI转为canvas代码,也是还原度低,对于复杂海报样式很难实现,更难二次调整;
尝试SVG绘制
SVG是在浏览器上可行的,UI设计师出稿一个SVG模板,详情页信息(文字/图片)直接拼接/导出到SVG中,生成海报图片,但是小程序不支持SVG,所以依然不可行;
最终解决方案
使用Taro原生的Snapshot组件,只需要写原生的Taro代码,会被截图为画布,渲染结果导出成图片,需要局部开启Skyline模式,但是总算是实现了浏览器中Html2Canvas的效果,参考文档 docs.taro.zone/docs/apis/s...
参考代码
sharePoster.tsx
tsx
import { useRef, useCallback } from 'react'
import Taro from '@tarojs/taro'
import { View, Text, Button, Image } from '@tarojs/components'
import './poster.css'
export default function PosterPage() {
// 1. 创建 ref 获取海报容器节点(Skyline 节点)
const posterRef = useRef<View>(null)
// 2. 声明 Snapshot 实例
let snapshotInstance: Taro.Snapshot | null = null
// 🔥 核心:生成海报(截图)
const createPoster = useCallback(async () => {
try {
// 校验节点
if (!posterRef.current) {
Taro.showToast({ title: '节点不存在', icon: 'none' })
return
}
// 1. 初始化 Snapshot 实例(官方标准用法)
snapshotInstance = Taro.createSnapshot()
// 2. 获取 Skyline 节点的 ID(必须通过 ref 获取)
const nodeId = posterRef.current._nodeId
// 3. 执行截图(核心 API)
const res = await snapshotInstance.takeSnapshot({
nodeId, // 要截图的 Skyline 节点 ID
// 可选:自定义截图尺寸/质量
quality: 1,
type: 'png'
})
// 4. 截图成功:res.tempFilePath 是海报临时路径
const posterPath = res.tempFilePath
console.log('✅ 海报生成成功:', posterPath)
// 可选:预览海报 / 保存到相册
Taro.showToast({ title: '生成成功', icon: 'success' })
Taro.previewImage({ urls: [posterPath] })
} catch (err) {
console.error('❌ 海报生成失败:', err)
Taro.showToast({ title: '生成失败', icon: 'none' })
}
}, [])
return (
<View className='page-container'>
{/* 🔥 海报容器:Skyline 渲染节点,ref 绑定 */}
<View ref={posterRef} className='poster-box'>
{/* 这里写Taro原生代码,海报内容(可自定义:图片、文字、头像等) */}
</View>
{/* 生成按钮 */}
<Button className='create-btn' onClick={createPoster}>
生成海报
</Button>
</View>
)
}
需要在专门的分享页开启skyline xxx.config.ts
ts
export default {
navigationBarTitleText: '生成分享海报',
skyline: { enable: true },
defaultRenderEngine: 'skyline',
disableScroll: true
}
建议在详情页点击分享->生成分享海报按钮时,跳转该页面,生成完成后携带res.tempFilePath临时路径 返回详情页,然后展示和下载海报图片。因为skyline模式的无法使用第三方UI组件,建议单独独立为一个局部页面。