在最近的H5项目中使用了html2canvas实现让用户上传照片并且可以添加文字,图片贴纸等素材生成背景图。记录下开发过程中遇到的问题
生成空白图片
在开发过程中发现html2canvas生成的图片都是空白图片,这是因为调用html2canvas方式时传入了useCORS: true。只有开启了跨域请求的图片才能被画到canvas里否则会被视为“污染”。项目中图片都在阿里云上并且限制了请求域名导致生成图片时加载图片失败了而白色底图是html2canvas的backgroundColor属性。发现问题后让运维同事把新的域名加上后再试了下满心欢喜得以为就要成功了结果还是不行只能继续排查。原来在生成图片之前已经在图片列表中加载过一次了,而图片列表中的图片没有开启跨域浏览器会缓存请求过的资源,所以生成图片时发起的请求是之前没有开启跨域的缓存,在生成图片时地址后面加上时间戳就解决了
有缩放样式的元素生成的图片变小了
刚解决了跨域问题产品又提出了生成多张图片的需求,用户可以选最多5张图片进行编辑以轮播图的方式展示,为了实现轮播图视差效果给元素添加了scale属性结果生成的图片也被缩放了。用onclone把元素样式变成scale(1)就好了该方法不会影响页面展示
生成图片慢
当我自信满满得提测时测试提出来生成图片太慢了,开始以为是网络问题但是经过测试5g网络下生成一张图片也需要4s左右,生成多张图片有时需要等待30s,没办法连我自己都等不下去,只能继续解决问题了。真是一坑又一坑坑坑不一样。通过观察network发现生成图片时竟然把所有资源都请求了一遍,自测时图片列表只有几张图片而测试环境有十几张,浏览器一个域名下最多能并发6-8个请求超过的都会排队等待,怪不得能这么慢。查看源码发现DocumentCloner会克隆一份新的document,除了我们想要变成图片的元素外其他的节点也会被克隆,我们需要忽略这个节点
html2canvas有两种忽略节点方法
- 在元素上添加 data-html2canvas-ignore 属性
- 使用 ignoreElements 返回true表示要被忽略
data-html2canvas-ignore并不会作用于子元素,如果页面结构比较简单使用第一种就行了,页面比较复杂的话在每个元素上添加 data-html2canvas-ignore 属实麻烦,可以用第二种方法代替。判断如果满足节点是目标节点或者是目标节点的父元素或子元素或者是style link标签就去克隆节点。
compareDocumentPosition是判断两个元素之间的位置的DOM方法, 20代表16(目标元素在element之内)+4(目标元素在element之后)
修改之后在测试下生成单张图片的时间基本在1s左右,生成5张图片在6-8s左右