html2canvas遇到的坑

需要将一个背景图+动态获取的微信名+微信头像拼接成一张图片,用户可长按保存最终图片,最终就是要将html转换成图片。
最初想自己用canvas画,但是有些麻烦,后来发现了html2canvas这个插件,先将html转成canvas,再生成图片。

因为生成的图片和html是在同一个页面中,最初想法是页面加载完成后,html内容隐藏,对应的图片盒子生成并显示,在实现过程中发现如果将html内容隐藏,图片会生成失败。
于是换一种思路,将html内容定位在页面底部,canvas生成的图片做一个层级遮罩,完美~

1、清晰度的问题:

网上有很多将教你设置canvas的scale,然后保存。我试图将倍数放到n倍,可是依然模糊,再此过程中,发现了类似的生成图片的库dom-to-image,结果更加的模糊到可怕,因为一开始的类库是从网上随意找了插件拿过来的版本,最后我尝试将html2canvas.js版本更新到最新版本(官网下载最新版本),问题得以解决。(另,在实现过程中发现如果图片作为background-image时,依然是有些模糊的,换成页面引入图片即可解决)

官网地址:http://html2canvas.hertzen.com/

2、图片跨域问题:useCORS:true,allowTaint:false
设置 useCORS: true , 如果使用以上跨域方法, 若同时设置为 allowTaint: true , 会认为画布已被污染而不可用;

3、图片显示半截或者图片无法显示问题:

解决办法如下:
1)添加3000毫秒延迟加载,2)图片全部加载完成后,再调用生成图片方法,3)头部添加<meta http-equiv="Access-Control-Allow-Origin" content="yes">,4)给引入图片添加属性crossorigin="anonymous"(为后边的bug埋下了伏笔,巨坑!)

function takeScreenshot() {
        setTimeout(function(){  //添加3000毫秒延迟,防止图片没有加载完成,就生成canvas,导致页面图片空白
            html2canvas(document.querySelector("#posterHtml"),{useCORS:true,allowTaint:false}).then(canvas => {
            var dataUrl = canvas.toDataURL();
            console.log(canvas.style.width);
            console.log(canvas.style.height);
            //  $("#posterImg").width(canvas.style.width).height(canvas.style.height)
            document.getElementById("posterImg").children[0].src = dataUrl;
            });
        },1000);
    }
    $('#posterPrizeimg img').on('load', function() {
        //图片加载完成 调用生成图片方法
        takeScreenshot();
    });

4、图片偶现问题!

这个问题困扰了我很久,图片偶现,既然会出现,肯定跟跨域没啥大的关系了,到底是什么原因呢,因为第二天要上线,尝试了各种办法未能得到解决,最终在大佬的一篇博客中得以解决,非常感激大佬的分享!

因为偶现的问题,我一直在删除之前的 crossorigin="anonymous"属性做各种尝试,结果发现之前手机完美展示的反而图片不显示,之前图片不显示的反而完美呈现?

扫描二维码关注公众号,回复: 5407127 查看本文章

-引用:原因跟html2canvas库的工作原理有很大的关系。如前文所说,html2canvas库需要我们先提供一段DOM节点,然后它再读取并解析这一段DOM节点生成canvas对象。如果DOM节点中已经使用了<img>标签的话,它也会解析这个<img>标签的src属性,然后重新创建一个Image对象,给它添加crossOrigin="anonymous"属性后尝试以跨域的方式重新读取图片数据。需要注意的是,一般CDN上的图片都是带有缓存响应头并且会在浏览器端缓存的,而且缓存的不仅仅是图片数据,还有HTTP响应头。所以问题的根本原因我们就找到了,当html2canvas尝试以跨域的方式去读取图片数据时,它读取到的是浏览器的缓存数据,而且因为我们没有给DOM节点中的<img>标签添加crossorigin="anonymous"属性,所以缓存数据是不带Access-Control-Allow-Origin响应头的,进而导致html2canvas库读取到的图片数据污染了生成的canvas对象,最终致使canvas导出数据报错。

事情是这样子的,如果你要用来生成canvas的dom中包含的<img>图片,之前已经被你的用户访问过(例如你是在对线上现有的业务进行改造),显然之前你应该没有给<img>标签添加crossorigin="anonymous"属性,那么请注意,这时候你的用户的浏览器已经把这些图片缓存在了本地,所以即便你按照上面的步骤都做了也没用,因为访问图片时读到的都是不带Access-Control-Allow-Origin等响应头的缓存数据。

这个时候你要做的,就是给要生成canvas的dom中的所有<img>标签的src添加一个任意的字符串,只要能起到重新发起图片读取请求,从而避免读取到浏览器缓存数据即可,如下所示:

'http://h0.hucdn.com/open/201819/9404b56f97e7df8a_750x1334.png?any_string_is_ok'

注意,不要添加随机字符串,那会击穿CDN缓存的,随便添加一个固定的字符串,能够避免读取到浏览器的缓存数据就可以了。这是本人血的教训!所以请大家千万千万不要忽视这一点!引用结束--
链接:https://www.jianshu.com/p/22bd5b98e38a

当我看完这断文字的时候,我就觉得真相终于找到了。

于是我在我的每张图片后边追加固定字符串,再次发版测试,完美解决~

猜你喜欢

转载自blog.csdn.net/dream0129/article/details/86983023
今日推荐