手把手教你使用html2canvas

1,386 阅读3分钟

序言:canvas真的很重要,闲来无事大家可以多玩玩,在做这个的时候我也是一直在尝试不使用第三方库直接canvas绘制然后转成base64

1.什么场景下使用

当你需要前端将将页面截图成图片分享到微信时,这个时候你就应该想到canvas,当然比较成熟的库就是html2canvas.此外还有dom-to-image

2.html2canvas原理是什么

集合了业内两种实现思路,一种是canvas,另一种是svg,具体使用哪种需要看具体场景,有兴趣的可以拜读下源码

2.1 canvas

  • 递归取出目标模版的所有DOM节点,填充到一个 rederList ,并附加是否为顶层元素/包含内容的容器 等信息
  • 通过 z-index、 postion float 等css属性和元素的层级信息将 rederList 排序,计算出一个canvas的renderQueue
  • 遍历renderQueue,将css样式转为 setFillStyle 可识别的参数,依据nodeType调用相对应canvas方法,如文本则调用 fillText ,图片 drawImage ,设置背景色的div调用 fillRect 等
  • 将画好的canvas填充进页面,利用canvas.toDataURL()转成base64

2.2 svg

  • 首先,我们要声明一个基础的svg模版,这个模版需要一些基础的描述信息,最重要的,它要有 这对标签
  • 将要渲染的DOM模版嵌入 foreignObject
  • 利用 Blob 构建svg图像
  • 取出URL,赋值给img

3.如何使用

//html2canvas(targetDom).then(canvas => { // append canvas to page });





html2canvas(this.$refs.imageSave, {

useCORS: true

}).then((canvas) => {

let dataURL = canvas.toDataURL('image/jpeg', 0.6)

})

4.遇到的问题

4.1 如何控制分享图片大小

直接控制生成canvas的style

html2canvas(this.$refs.imageSave, {

useCORS: true

}).then((canvas) => {

canvas.style.width = imgWidth * 0.8 + 'px'

canvas.style.height = 400 + 'px'

let dataURL = canvas.toDataURL('image/jpeg', 0.6)

})

4.2 跨域?一步一个坑!

坑1:

解决方案:useCORS: true

坑2:

看到ACAO不要多想,

1.服务器配置了吗 配置对了吗(域名,端口), 别小看端口,线下测试环境一般是带端口的,线上一般不带,运维说必须要带,默认是80, 千万别信!!!, 带上你就别想绕过去,因为带了80端口坑了我半天,才有了后边的bug

2.还是这个问题,当你配错一次之后,以后配对也不好使了,就问你气不气,没关系毕竟他之前是好使的,这个时候你要想到的就是 缓存 (没错这个东西你想要的时候不来不想要的时候他就一直在这里),我们的解决办法加个字符串

不要用随机字符串,他会击穿cdn,很关键

this.imgUrl = this.$route.query.imgUrl + '?v=234'

坑3:

点击分享太快,图片还没有加载完成,不要小觑这个也可能造成acao

解决方案:加入img onload

坑4:

和客户端交互

解决方案: base64你不知道的事

坑5:

ios9 以下 调用html2canvas img src base64格式的图片不展示

解决方案:降低html2canvas版本 到 1.0.0-rc.0

原因追溯:

装包法缩小范围:通过装不同版本的包发现 1.0.0-rc.0 升级到 1.0.0-rc.1出现了问题

查看github 提交记录,发现有如下改动

进入修改细节查看,基本定位是

具体代码如下

github.com/niklasvh/ht…

后边拿到测试机自己修改看下,然后提个pr,就酱

4.3 其他坑

4.3.1 background 比 img 模糊,尽量多使用 img

4.3.2 ios 8 不支持 flex 详见: www.jianshu.com/p/059e7b6cc…

4.3.3 position:absolute fixed 不支持

写在最后:有bug没关系,不要慌,google + github 的 issue + 经验脑洞 bug 就能解决

参考地址:

juejin.im/entry/58b91…

www.jianshu.com/p/22bd5b98e…