前言
最近开发上线了一个微信裂变活动,用户生成自己的海报,邀请其他用户帮忙助力。因为是在h5的环境下,使用了htm2canvas
来生成分享海报。结果上线收到少部分用户反馈无法生成海报,点击按钮后没有反应,查看告警平台也并没有相关的错误日志捕获。结果修复这个问题后,后续还产生了一系列的生产环境的问题,吓得我差点提桶跑路。
html2Canvas
html2Canvas
是一个比较成熟的开源库,它能将DOM直接转为Canvas,省去了使用原生Canvas需要一点一点去绘制的过程。
使用
以vue中使用为例
// 安装依赖
npm install --save html2canvas
//使用
<template>
<div>
<div ref="canvas">html2Canvas</div>
<button @click="toImg">生成图片</button>
</div>
</template>
<script>
import html2canvas from "html2canvas"
export default {
methods: {
toImg() {
html2canvas(this.$refs.canvas, {}).then(canvas => {
})
}
}
}
</script>
常用配置项
参数 | 类型 | 默认值 | 描述 |
---|---|---|---|
allowTaint | boolean | false | 是否允许跨域图像污染画布 |
useCORS | boolean | false | 是否跨域加载图片 |
backgroundColor | string | #fff | 背景色 |
width | number | 元素宽度 | 单元格 |
height | number | 元素高度 | 单元格 |
scale | number | window.devicePixelRatio | 缩放比例 |
scrollX | number | 元素x轴滚动位置 | 生成后x轴滚动位置 |
scrollY | number | 元素y轴滚动位置 | 生成后y轴滚动位置 |
html2Canvas绘制跨域图片
首先在线图片域名需要配置允许跨域访问;
然后img标签需要添加crossorigin="anonymous",src后面添加时间戳防止被缓存(这里最好不要添加时间戳,后面发现cdn被击穿的问题,可以使用一个固定的字符串,比如 v=1.0.0 这种);
<img
crossorigin="anonymous"
class="share"
:src="src+'?'+new Date().getTime()"
>
最后就是html2Canvas添加{allowTaint: true,useCORS: true}配置项。useCORS: true和上面crossorigin="anonymous"起到的作用是一样的(二选一即可,感兴趣的可以在源码里看一下,这个配置项就是影响给不给图片添加crossorigin="anonymous")
html2canvas(this.$refs.canvas, {allowTaint: true,useCORS: true,}).then(canvas => {
let imgUrl = canvas.toDataURL()
})
缺点:它并不支持所有的css属性,详情可以参考官方文档 文档
排查问题
因为没有捕获到错误日志,我们项目组主流机型也都测试过,初步分析可能是因为手机系统问题,各种收集资源,终于在一个ios13.4的系统复现出该问题了————html2canvas回调函数不执行。
解决问题
问题一:ios13.4.x系统html2canvas在微信浏览器下回调不执行
查阅各种资料后,在一个 issues 看到了解决方案:需要将html2canvas版本回退到1.0.0-rc.4。
最简单的方式就是直接修改package.json,改为"html2canvas": "1.0.0-rc.4",然后重新安装依赖就行。 重新打包后,一看这个问题果然好了,以为万事大吉了,部署到测试然后出现了第二个问题————ios14.x版本跨域图片空白了
问题二:html2canvas 1.0.0-rc.4版本导致ios14.x系统下无法绘制跨域图片
又继续查阅资料,找到了解决上一个问题的第二种方案,不用旧版本js文件了,有大佬直接修改了新版的源码,将回调不执行的问题规避掉了。
直接下载修改后的html2canvas.js源码下载地址放到项目工具类目录下,使用本地文件的方式引入。
// 引入
import html2canvas from '@/utils/html2canvas.js';
问题三:在ios15.1系统生成时会刷新页面
上次修改发布后项目已经稳定运行一个月了,结果从苹果的新品发布会之后又陆续收到用户反馈苹果13无法生成海报,当时新机也是刚发布,查阅不到相关的资料,手里也没有测试机。也就只能天天顶着客诉。熬了几天终于有同事用上新手机,看到了曙光,第一件事就是新机拿来调试,排查后发现问题了:如果html2canvas要绘制的容器内有能包含文本的标签不设置字体的话系统会默认给添加font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
这样就会导致刷新页面。
解决方法就比较简单了,给所有需要被绘制的标签设置一下字体即可。
总结
这次暴露了几个使用html2canvas会遇到的比较偏门的问题,特别整理出来,希望别人就不用走弯路了。
关联阅读
这几天经过大佬们的指导,落地了新的海报生成方案。这个方案目前我感觉是最简单,且复用性高的 《Node+Puppeteer生成海报》