手记
下载APP

html2canvas项目中遇到的那些坑点汇总(更新中...)

1. 截图模糊

    原理就是讲canvas画布的width和height放大两倍。

  后来学习canvas的时候,才了解到这种写法不同于css的宽高设置,

  因为css里的只是展示画布显示的大小,不像这样是canvas真正的内里图画分辨率的大小。

https://img.mukewang.com/5c6136740001025906410429.jpg

2. 元素设置文字阴影,截图后阴影错乱,所有元素都会有阴影

  起初以为是v1.0.0-alpha.12 最新版本的问题,后来改成5也不行,把文字阴影去掉就可以了。

  这个问题在大神的博文中有解决方案:https://blog.csdn.net/SDUST_JSJ/article/details/78122610  

以下为针对本问题的部分摘录: 

 文本设置text-shadow截图后却没有文本阴影(2017-09-28)

  bug原因

  查看了源码,html2canvas确实处理了text-shadow,但是没有正确的处理小数,导致最后文本阴影没有显示出来。 

  解决方案

  针对这两行的正则表达式,我添加了针对小数的判断,修改后的代码如下:“由于篇幅限制,源码请看原博”

 文本阴影效果没有显示(2017-10-18)

  现象及原因

  现象:部分文本设置了阴影效果,但是截图后并没有显示出来。 

  原因:html2canvas库确实解析了阴影样式,但是并没有绘制,只是当做变量存起来了。 

  解决方案

  使用canvas context提供的阴影方法绘制阴影: 

  第3044行,将fontShadow 函数改为如下所示:

CanvasRenderer.prototype.fontShadow = function(color, offsetX, offsetY, blur) {  

“由于篇幅限制,源码请看原博”

};

文本描边和阴影同时显示时显示不正常(2017-10-18)

  现象及原因

  现象:阴影特别严重,甚至看起来有点模糊。 

  原因: 和canvas context何时调用strokeText方法有关。具体原因在解决方案中描述。

  如果有阴影,一开始就渲染stroke,之后的内容会覆盖一部分stroke的内容;如果没有阴影,最后渲染stroke,stroke会覆盖filltext函数渲染的内容。 

  先渲染text,如果有阴影,同时渲染阴影,然后将阴影效果去掉;如果有描边,渲染描边效果。经确认,这种写法比之前的写法要好。(2017-10-19)

  以上摘自:

  csdn   https://blog.csdn.net/SDUST_JSJ/article/details/78122610

  作者: kylin_zdd1993

3. 水平居中的元素截图后向左跑偏

  明明是水平居中的代码,截图出来的会偏左,结构是左图片右文字,有时候是图片自己跑到最左边,有时候是整体偏左一点点

  这个问题也不是经常遇到,场景是父div元素text-align=center;内部两个子元素设为display:inline-block的模式。然后画图就会出现左边的div偏左靠或直接在左边的情况。

  问题未解决,出现时也没研究因为啥,等有时间的时候就不出现了。。。

4. 靠背景图露脸的dom们会有底线。即如果元素使用背景图呈现,那么截图完毕会有一条下边线

  截图时,如果有一个dom元素是用背景图填充的,里边没有任何结构,那么截图出来的底部会有一条和背景图底部一致的一条线

  像是背景图y轴重叠,然后差那么一像素没铺满的感觉。

   比如这样一张图:

https://img2.mukewang.com/5c61374700019cc003510098.jpg

    截出来长这样:

https://img1.mukewang.com/5c613747000161d503690095.jpg

  项目暂时解决方法,蓝色背景用颜色不用整块的图片显示。

  这种图片普遍有一个规律就是,有投影,图片的正常高度要高于有颜色区域的高度

  如这张图:https://img.mukewang.com/5c6137470001898b01020063.jpg

  

        底部部分:https://img.mukewang.com/5c6137470001c1e001070061.jpg

 

  有时候靠拉伸/压缩一点点dom元素的高度解决了,有时候又不行。

5-1. 背景图做的元素,截图出来图也是很模糊的,设置倍数也没用。

5-2. 在iphone 7plus中,即使没有背景图截出来的还是有一条边线...

下边是黑色背景色+小点点,就这样的布局,一个背景色都没有,为什么截图下来还是有条线?而且还是部分手机中的ip7!

6. 报错:the operation is insecure

    canvas.toDataURL 报错 the operation is insecure

  canvas.toDataURL(type, encoderOptions);语法

  配置如:canvas.toDataURL("image/png", 0.7); 

  参数type指定图片类型,如果指定的类型不被支持则以默认值image/png替代;

  encoderOptions(第二个参数)可以为image/jpeg或image/webp类型的图片设置图片质量,取值0-1,超出则以默认值0.92替代。

7. 不可见的元素截图后是空白

    没法截图看不见的,比如opacity为0的东西,或者visibility为hidden的,更别说display:none了。都不行,

  截出来的一样是白色的,可想而知,毕竟没截上东西当然就是白色了。

  解决方法是让canvas部分隐藏到后边。最终选择方案,层级设为-1,上一层的把他盖住。

  前提是上一层要又一个可以设置的背景色,能把他盖住不被用户看到

8. html2canvas结合微信里的长按存图功能

  先用html2canvas拿到一个html转为canvas的base64码,

  再在页面建立一个img元素,src=base64码,插入dom中,盖在所有元素的最上方(或者需要用户长按保存的地方),opacity设置为0。

  然后用户就长按保存,存下来的就是事先准备好的覆盖在那里的那个不可见得透明图。

  事实证明,图片透明不可见覆盖在页面上边,微信里是可以存图的。

  而很多市面上的h5,结果页和最后存下来的图不一样的,估计都是这么搞得,毕竟看不见代码

9. html2canvas+jsbridge同时存两张图

    html2canvas和jsbridge的存图功能协作时,会触发同时存两张图的现象。

  第一次存图很完美,如果不关掉页面第二次存图,就会存两张,以后也会存两张。只有第一次使用存图是好的。

  就是jsbridge调了两次,第二次自动调起的原因目前猜测是html2canvas引起的, 

  因为一层层定位,只有在html2canvas返回base64码后会有问题。具体原因暂没有找到。

  最后解决方法是:配合sessionStore,第一次截完图后,将图片地址存入sessionstore,

  之后判断,sessionstore里有base64码就不用html2canvas生成码了,直接取数据存图,

10. html2canvas触发时重新加载页面的所有静态资源(除js)

  css和img图像,这一点是在和Wdatapicker组合使用时发现的问题。

  本来没什么,爱加载几次加载几次,但是datapicker的样式是写在iframe里的,重新加载dom还把人家的样式给丢了。这事儿就大了

  大归大,问题根本原因没解决,还是治标不治本的在每次触发html2canvas截图保存pdf的时候,重新给datapicker绘制样式,就是这么任性!

11. html2canvas 截图跨域

  图片跨域时报错现象

  这个时候你要去看图片的header头有没有这个:

Access-Control-Allow-Origin:  *

  看图片本身是否允许跨域访问:

  

上边这个是一个允许的图片。

下边这个不允许,就截取不到。

    这篇博文对于html2canvas跨域讲解很细致: https://blog.csdn.net/yaosir1993/article/details/76474080

  以下截取部分作者思想,主要是用于解决了本次问题的地方:

  useCORS:true 这个参数很重要,没有配置的话,依旧是不能解决问题的;

  根据现有的解决方案大致有两种: 

  (1).在跨域的服务器上设置header设置为允许跨域请求。 在服务器上设置header设置允许跨域请求(采用nginx做静态资源映射) 

  (2).借助代理脚本获得外域图片的 base64 编码后的字符串 

  关于跨域和清晰度解决方案的讲解地址:https://lengxing.github.io/ 

  设置header,实现跨域访问http://blog.csdn.net/enter89/article/details/51205752 

  解决建议:

  域名反向代理,

  图片允许跨域使用:Access-Control-Allow-Origin: *;

12. html2canvas+qrcode 截二维码被白底遮挡(有背景设置的元素截图后,背景色把图片盖住)

  html2canvas执行截图-因为页面中有一处是qrcode执行的地址转二维码,每次截图后二维码都截不下来,那一块就是一个白块.

  按理说二维码图片是base后的地址不应该啊。

  后来把二维码img的外部div元素的背景色设置半透明,二维码就隐约能看出来了,原来是div的背景色盖住了img。

  原理还是搞不明白,明明层级都设置了还不起作用,竟然被自己的爹给盖住也是醉了。

  二维码处之所以为白色是因为外部结构的白色背景给覆盖了,最后是盛放二维码img的外部div结构不设置背景色就解决了

13. html2canvas截图时,背景音乐在IOS11下会重复播放

  解决方法见博文:https://blog.csdn.net/lerayZhang/article/details/79207468

14. html2canvas截图,省略号失踪?!

     2018-09-27 17:49:09

  这种情况,之前同事遇到过,问我我说没遇到过,后来找产品协调不要省略号。然后也没当回事。

    最近又被博友问起,我刚好在做类似项目,就顺手模拟了一下效果,如下:

  然后不出意料的出现了几个堪比车祸现场的问题:

  请看三种的依次截图效果:

  其一当然是本问题主题,即省略号丢失的问题

  其二请观察图二,你会发现,用了padding的元素,他的截图中,左padding还在,右padding没了,而是被文字给填充了.

  先说回省略号的问题,我猜想和canvas机制有关,

  因为毕竟canvas里边绘制文字不会换行,

  然后html2canvas可能是获取文本进行的fillText/strokeText()的绘制,而省略号并不是实际dom结构中的文本。所以获取不到?

  突发奇想,那伪类里边的content的内容他可以拿到吗?答案是可以。

  在图三中,我将省略号作为伪类的内容,利用伪类模拟超出显示省略号的效果进行截图,最后省略号截了下来.

  加上以往经验可以说明,内容放在伪类中也是可以被拿到的。所以我刚才 对于伪类不能被截下来的设想可以消灭。放心大胆的用伪类吧!

  但是但是,问题还是没解决额,这种模拟的效果太脆弱了吧!

  稍微文字多一个少一个标点,最后边文字会因为overflow:hidden;被截成半块。如图:

  所以在这里只是为了抛转引玉,

  有了这个模拟省略号的思路后,不知道各位看官大佬们还有更好的方法解决这个问题嘛?

  可以做到既不让省略号消失,也不让实际文字内容被劈成两半?

抛砖引玉的代码(pug语言):

“由于篇幅限制,源码请看原博”

js代码:

其他说明:

  经过这几次的html2canvas填坑记,我发现,使用html2canvas@1.0.0-alpha.5版本,配套上我们自己封装的html2img,总算坑可以少点了。正常的需求还是可以实现了。



打开App,阅读手记
2人推荐
随时随地看视频慕课网APP