Taro中使用html2Canvas和wxml-to-canvas
建议页面中正常写
taro
的代码,用于页面的正常展示
举个🌰
html
<div class="container" ref="h5Qrcode" >
<view class="item-box red">
</view>
<view class="item-box green" >
<text class="text">yeah!</text>
</view>
<view class="item-box blue">
<image class="img" src="https://img0.baidu.com/it/u=4154833386,1880487480&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500"></image>
</view>
</div>
html2Canvas
使用非常简单,只需提供dom节点,但仍需注意两个重点
-
需要动态引入,需要判断环境,不能在小程序中引入
typescriptimport { isWeb } from '@/utils/is'; // ... if (isWeb) { Taro.showLoading(); try { const html2Canvas = require('html2canvas'); html2Canvas(h5Qrcode.value).then((canvas) => { const imgBase64 = canvas.toDataURL('image/png'); Taro.hideLoading(); imgUrl.value = imgBase64.split(',')[1]; handleSaveToAlbum(); }); } catch (_) { Taro.hideLoading(); } }
-
该插件需要的是原始的dom节点。在taro中,如果通过
<view>
获取ref
,会有差异,并不是原始的dom会报以下错误
Error: Element is not attached to a Document
这个通过view拿到的ref,虽然身上有
$el
属性,但通过实践得知,图片会出现问题。所以细心的你应该会说了,答案从一开始不就展现了吗,不写
<view>
而写<div>
,没错,通过div
,能拿到我们熟悉的原始dom
wxml-to-canvas
这是微信小程序官方推出的库,使用wxml的template和样式,转换为canvas,和html2canvas一样方便;但同时他也没有那么地方便。因为你除了正常画页面外,额外维护一套wxml和style,才能使用wxml-to-canvas
-
该库依赖于
widget-ui
,先安装依赖shnpm i widget-ui
然后想办法搞到wxml-to-canvas打包后的产物,我是通过安装wxml-to-canvas依赖,然后从node_module中复制出来的,当然你可以选择克隆git,然后运行打包命令。
然后将这个小程序的产物放到我们的项目当中,同时要注意,如果你放在了分包中,那么只能在该分包下引入使用,其他地方想引用是不行的。所以我建议是放到主包中,因为很多地方要使用,当然,具体得看需求。
假设我放到主包的component文件夹中
-
在config/index中增加配置
javascriptconst config = { designWidth(input) { if (input?.file?.replace(/\\+/g, '/').indexOf('@nutui') > -1) { return 375; } return 750; }, ... mini: { ... compile: { exclude: [(modulePath) => modulePath.indexOf('component/Mini') >= 0], }, } }
设置好
mini.compile.exclude
,意思是匹配到路径包含component/Mini
就忽略,不经过taro的编译,因为这个本来就是小程序的代码了。 -
具体的页面中引入使用。要使用原生小程序的组件,那就必须通过
definePageConfig
的usingComponents
属性注册typescriptdefinePageConfig({ navigationStyle: 'custom', usingComponents: { 'wxml-to-canvas': '../../../component/Mini/wxmltocanvas/index', }, });
在template中使用
html<template> <template v-if="!isWeb"> <wxml-to-canvas class="widget"></wxml-to-canvas> </template> <!-- 其他东西 --> </template>
-
编写wxml和style。根据文档提示,写好自己的东西
typescriptconst wxml = `<view class="container" > <view class="item-box red"> </view> <view class="item-box green" > <text class="text">yeah!</text> </view> <view class="item-box blue"> <image class="img" src="https://img0.baidu.com/it/u=4154833386,1880487480&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500"></image> </view> </view> `; const style = { container: { width: 300, height: 200, flexDirection: 'row', justifyContent: 'space-around', backgroundColor: '#ccc', alignItems: 'center', }, itemBox: { width: 80, height: 60, }, red: { backgroundColor: '#ff0000', }, green: { backgroundColor: '#00ff00', }, blue: { backgroundColor: '#0000ff', }, img: { width: 80, height: 60, }, text: { width: 80, height: 60, textAlign: 'center', verticalAlign: 'middle', }, };
-
接着就是调用方法,渲染,获取图片等自定义操作了
typescriptconst widget: any = Taro.getCurrentInstance().page?.selectComponent?.('.widget'); await widget.renderToCanvas({ wxml, style }); // 生成图片 const res = await widget.canvasToTempFilePath(); const tempFilePath = res.tempFilePath; // 调用taro相关api下载tempFilePath;
结语
注意判断不同的平台(web和微信小程序),这两个库都是针对性的。