html2canvas.js 图片跨域 生成图片模糊 图片偏移 高清图的问题总结

首先 本人是一个canvas小白 基本不懂canvas的原理,拿到同事写的代码直接copy过来也没看文档(项目催的紧且文档是英文的) 话很少说 上代码 只是说出个人解决思路不少为何还要花时间研究 好比canvas我都不会css

<script src="https://cdn.bootcss.com/html2canvas/0.5.0-beta4/html2canvas.min.js"></script>
复制代码
html2canvas(document.querySelector(".upload_box")).then((canvas) => {
    
        var imgData = canvas.toDataURL('image/png');
      
        $('#save_img').html($('<div id="downLoadImg"><img src="' + imgData + '" alt=""></div>'));

    })
复制代码

如此简单是否是!获取dom 把返回的canvas转成图片显示! 遇到两个问题:html

  • 部分图片没有生成
  • 生成的图片特别模糊(文字和图片都是模糊的)手机上更糊

但是为啥同事的代码没有问题呢!我拉来了同事 发现了一个问题:dom涉及到的图片不是本地的话 生成不出来 当时试了好多方法 都不行(这个时候傻逼的我为啥不去看看文档!)总之在网上试了好久 最终的作法是把从服务器获取的图片都转成base64显示 (网上找的代码) 暂时解决了

getBase64: function getBase64(img) {//传入图片路径,返回base64
                function getBase64Image(img, width, height) {
                    var canvas = document.createElement("canvas");
                    canvas.width = width ? width : img.width;
                    canvas.height = height ? height : img.height;
                    var ctx = canvas.getContext("2d");
                    ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
                    var dataURL = canvas.toDataURL();
                    return dataURL;
                }

                var image = new Image();
                image.src = img;
                image.crossOrigin = "Anonymous"
                var deferred = jQuery.Deferred();
                if (img) {
                    image.onload = function () {
                        deferred.resolve(getBase64Image(image));//将base64传给done上传处理
                    }
                    return deferred.promise();//问题要让onload完成后再return sessionStorage['imgTest']
                }
            },
            
复制代码
_this.getBase64(resp.avatar)
    .then(function(base64){
    // console.log(base64);
        $('.user_info .user_head img').attr('src',base64)
    },function(err){
        console.log(err);
    });
复制代码

模糊我都不想处理了 !可是产品说不行啊,你这个生成的图片二维码都识别不出来 必需要清晰 就在我加班到早上六点也解决不了的时候 产品说能够先隐藏这个功能,花时间研究一下。 因而次日 我就开始准备找方法了。

首先把官方文档看了一遍:html2canvas.hertzen.com/configurati… 虽然是英文 但其实没多少东西 主要就是参数配置 一句句谷歌也能翻译出来(不要被英文吓到)程序员

看到了一个配置:useCORS false Whether to attempt to load images from a server using CORS 不就是容许跨域获取图片吗,为何以前试了这句好像没有效果呢?canvas

var opts = {
                                useCORS: true
                            };
                            
复制代码
html2canvas(document.querySelector(".upload_box"),opts).then((canvas) => {
    
        var imgData = canvas.toDataURL('image/png');
      
        $('#save_img').html($('<div id="downLoadImg"><img src="' + imgData + '" alt=""></div>'));

    })
复制代码

酱紫 远程的图片页也能够了 不会出现空白页!真是开心,比转成程base64方便多了 毕竟好几张图片都要转很麻烦(后面还有一个转化的大坑我这里没遇到,也是雷 后面会说) 并且转化以后的图片会更加不清晰!开心!后端

而后我就开始个人漫长的 研究怎么生成清晰图的探索之路了!(找到同事的代码,他啥都没有配置啊! 而后我发现html2canvas默认生成的canvas的宽高就是你dom结构的宽高 同事的代码截图的是整个网页 很大 生成的图片也就挺清晰的 ,可是个人截图模块只占网页不到1/2 过小了! 感受就是这个缘由,我开始想要说复制一个dom吧尺寸放大 可是以为太low了 因而仍是想尝试一下别的!跨域

固然能百度到不少promise

  • 最多的就是修改源码 技术很渣的我直接放弃了 不会改不敢改
  • 而后修改配置项啊 反正按照他们的说的方法
var width = $('.upload_box').width()
    var height = $('.upload_box').height()
    var canvasBox = document.createElement("canvas"); 
    var scale = window.devicePixelRatio; 
    canvasBox.width = width * scale; 
    canvasBox.height = height * scale; 

    canvasBox.style.width = width + "px";
    canvasBox.style.height = height + "px";
    canvasBox.getContext("2d").scale(scale, scale); 
   // 获取元素相对于视窗的偏移量
   var opts = {
        scale: scale, 
        useCORS: true,
    };
复制代码

差很少都是这样的写法 可是可是出来canvas是清晰了!可是不居中啊 尝试在配置项中增长参数 x y偏移 可是并无什么用 而后我就想 程序员怎么能用百度 !遂换谷歌 终于在 知乎里面看到一个好像比较看不懂的写法 因而就试试: www.zhihu.com/question/48…

做者:PajamaCat
连接:https://www.zhihu.com/question/48217555/answer/283209866
来源:知乎
著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。

前面的回答没有解决margin致使的生成图片偏移问题, 这里是解决方法:      var dom = $('#to-save-img')
      var width = dom.width();
      var height = dom.height();
      var type = "png";
      var scaleBy = 2; //缩放比例
      var canvas = document.createElement("canvas");
      // 获取元素相对于视窗的偏移量
      var rect = dom.get(0).getBoundingClientRect(); 
      canvas.width = width * scaleBy;
      canvas.height = height * scaleBy; 
      canvas.style.width = width * scaleBy + "px";
      canvas.style.height = height * scaleBy + "px";
      var context = canvas.getContext("2d");
      context.scale(scaleBy, scaleBy);
      // 设置context位置, 值为相对于视窗的偏移量的负值, 实现图片复位
      context.translate(-rect.left,-rect.top);
复制代码

就是这个所谓的偏移,我一看我要截图 dom的确是margin:0 auto的 是相对居中的 因此试试安全

var width = $('.upload_box').width()
                var height = $('.upload_box').height()
                var canvasBox = document.createElement("canvas"); 
                var scale = window.devicePixelRatio; 
                var rect = $('.upload_box').get(0).getBoundingClientRect(); 
                canvasBox.width = width * scale; 
                canvasBox.height = height * scale; 

                canvasBox.style.width = width + "px";
                canvasBox.style.height = height + "px";
                canvasBox.getContext("2d").scale(scale, scale); 
                canvasBox.getContext("2d").translate(-rect.left, -rect.top); 
                           // 获取元素相对于视窗的偏移量
                           var opts = {
                                scale: scale, 
                                canvas: canvasBox, 
                                // logging: true, 
                                // width: width*2, 
                                // height: height*2 ,
                                // allowTaint:true,
                                useCORS: true,
                                // x:-200,
                            };
复制代码

而后真的就行了!!!!!!! 激动啊激动啊简直大神啊!bash

而后我就很开心了 开心的发给测试 而后扑街 测试的手机上仍是彻底白板 啊?难道是兼容性的问题?但是咱们都是iphone7啊 ! 并且兼容性什么的最讨厌了! 我快绝望了 而后在个人手机上登录她的帐号 也是截图不了的 这太奇怪了 !难道是帐号的问题? 毕竟一成天都在解决所谓的跨域问题!图片跨域啥的不少啊! 服务器

而后果真 她的帐号的微信头像 : wx.qlogo.cn/mmopen/vi_3…

对这里就是我以前说到的转base64的坑 微信的头像不容许跨域,因此html2canvas没法直接使用微信的头像生成canvas,因此啊 我就想本地base64就行了 就一个头像,可是

查了一下是:污染的画布没法输出,发现原来是受限于 CORS 策略,会存在跨域问题,虽然可使用图像(好比append到页面上)可是绘制到画布上会污染画布,一旦一个画布被污染,就没法提取画布的数据,好比没法使用使用画布toBlob(),toDataURL(),或getImageData()方法;当使用这些方法的时候 会抛出一个安全错误

因此 我就妥妥的把问题丢给后端 让他们把微信头像转成base64给我了! 彻底搞定了!撒花

写下这个记录帖 虽然问题暂时解决了 可是还有更多的不懂在等着我去看

相关文章
相关标签/搜索