html2canvas转图片不清晰的解决方案

话不多说,直接上代码,自己写的小插件 不需要html2canvas也可以转

//调用示例 支持两种方式 
htmltocanvas.init({
	//支持html2canvas的参数
    background: '#fff', 
    showTag: !!1,  //显示标记 在控制台输出一些调试信息
    plus: !!1,  //为false的时候使用html2canvas转  为true的时候使用原生转换
    qrcode: !!1, //有二维码的时候传递true
    canvasCallBack: function (src) { //转成功时的回调
        
    },
},elm);

可能会有bug请自己完善

var htmltocanvas = (function () {
    var extend = {
        //默认输出标记
        showTag: !1,
        //默认使用兼容模式
        plus: !!1,
    };  
    return {
        tool: {
            createBase64Img: async function (scope) {
                var that = this;  
                return new Promise(function (resolve,reject) {
                    var num  = $('[data-img]',scope).length;
                    var flag = 0;
                    $('[data-img]',scope).each(function (i,e) {
                        var _src = $(e).attr('src');
                        if (_src.indexOf('data:image') === -1) {
                            var img = new Image();
                            img.src = _src + '?time=' + new Date().valueOf();
                            img.crossOrigin = 'Anonymous';
                            img.onload = async function () {
                                await that.imgSrcToBase64(img,$(e));
                                flag++;
                                htmltocanvas.tag('第' + i + '张图片的src已替换为base64','共有' + num + '张图片');
                                if (flag == num) resolve();
                            }
                            img.onerror = function () {  
                                reject();
                            }
                        } else {
                            flag++;
                            if (flag == num) resolve();
                        }
                    });
                });
            },
            imgSrcToBase64: async function (image,elm) {
                var that = this;
                return new Promise(function (resolve,reject) {
                    try {
                        htmltocanvas.tag('正在替换图片 ' + elm.attr('class'));
                        htmltocanvas.tag(image.src);
                        var canvas    = document.createElement("canvas");
                        canvas.width  = image.width;
                        canvas.height = image.height;
                        var ctx = canvas.getContext("2d");
                        ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
                        var dataURL = canvas.toDataURL();
                        elm.attr('src',dataURL);  
                        resolve();   
                    } catch (error) {
                        console.log(error);
                    } 
                });  
            },
            getDPR: function (){
                if (window.devicePixelRatio && window.devicePixelRatio > 1) {
                    return window.devicePixelRatio;
                }
                return 1;
            },
            isIos: function () {  
                return navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
            },
            plusCreateBase64Img: function (scope) {  
                var that = this;  
                var num       = $('[data-img]',scope).length
                    ,flag     = 0
                    ,deferred = $.Deferred();

                $('[data-img]',scope).each(function (i,e) {
                    var _src = $(e).attr('src');
                    if (_src.indexOf('data:image') === -1) {
                        var img = new Image();
                        img.src = _src + '?time=' + new Date().valueOf();
                        img.crossOrigin = 'Anonymous';
                        img.onload = function () {
                            $.when(that.plusImgSrcToBase64(img,$(e))).done(function () {
                                htmltocanvas.tag('第' + i + '张图片的src已替换为base64','共有' + num + '张图片');    
                                flag++;
                                if (flag == num) deferred.resolve();
                            });                      
                        }
                        img.onerror = function () {  
                            deferred.reject();
                        }
                    } else {
                        flag++;
                        if (flag == num) deferred.resolve();
                    }
                });

                return deferred.promise();
            },
            plusImgSrcToBase64: function (image,elm) {  
                var that     = this;
                var deferred = $.Deferred();
                try {
                    htmltocanvas.tag('正在替换图片 ' + elm.attr('class'));
                    htmltocanvas.tag(image.src);
                    var canvas    = document.createElement("canvas");
                    canvas.width  = image.width;
                    canvas.height = image.height;
                    var ctx = canvas.getContext("2d");
                    ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
                    var dataURL = canvas.toDataURL();
                    elm.attr('src',dataURL);  
                    deferred.resolve();
                } catch (error) {
                    deferred.reject();
                    console.log(error);
                } 
                return deferred.promise();
            },
        },
        init: function (option,scope) {
            var that = this;  
            $.extend(extend,option);
            if (extend.plus) {
                that.plusRenderCanvas(scope);
            } else {
                that.renderCanvas(scope);
            }
        },
        tag: function (msg) {  
            if (extend.showTag) {
                console.log(msg || '');
            }
        },
        renderCanvas: async function (scope) {
            var that = this;
            await that.tool.createBase64Img($(scope));
            that.tag('图片src替换已完成,正在渲染html2canvas...');
            var _h  = $(scope).outerHeight(),
                _w  = $(scope).outerWidth();
           
            var _canvas = document.createElement('canvas');
            var dp      = that.tool.getDPR();

                _canvas.width        = _w * dp;
                _canvas.height       = _h * dp;
                _canvas.style.width  = _w + 'px';
                _canvas.style.height = _h + 'px';    
            //TODO 处理canvas转出来的图片不清晰 
            //TODO 感觉还是不清晰,对清晰度有要求的同学可以使用 plusRenderCanvas
            var context = _canvas.getContext("2d");
            context.scale(dp, dp);
            var rect = scope.getBoundingClientRect(); //获取元素相对于视察的偏移量
            context.translate(-rect.left, -rect.top);
            extend.canvas = _canvas;

            html2canvas(scope,extend).then(function (canvas) {
                if (extend && extend.canvasCallBack && typeof extend.canvasCallBack === 'function') {
                    extend.canvasCallBack(canvas);
                }
            });
        },
        plusRenderCanvas: function (scope) {
            var that = this;
            $.when(that.tool.plusCreateBase64Img($(scope))).done(function () {  
                that.tag('图片src替换已完成,正在生成canvas...');
                var _h = $(scope).outerHeight() + 20,
                    _w = $(scope).outerWidth();
                //TODO 处理qrcode生成的二维码
                if (extend.qrcode) {
                    //FIXME 在IOS上面有BUG,还没有处理
                    if (that.tool.isIos) {
                        //TODO
                    }
                    $('canvas+img',$(scope)).attr({'style': 'display:block;','data-img': ''});
                }
                //TODO 在xhtml里面<img />标签必须要闭合,不然会报语法错误,并且也转不了svg
                //TODO 这里利用自定义属性[data-img]给<img>标签替换一个结束标记
                var divContent = scope.outerHTML.replace(/data-img="">/g,'/>');
                var data = "data:image/svg+xml," +
                    "<svg xmlns='http://www.w3.org/2000/svg' width='"+_w+"' height='"+_h+"'>" +
                    "<foreignObject width='100%' height='100%' style='background-color:rgb(255,255,255);'>" +
                    //TODO 这里必须要声明xmlns为:http://www.w3.org/1999/xhtml
                    "<div xmlns='http://www.w3.org/1999/xhtml'>" +
                    divContent +
                    "</div>" +
                    "</foreignObject>" +
                    "</svg>";

                var img     = new Image();
                    img.src = data;
                //TODO 必须要等img渲染完成后再进行下一步的操作
                img.onload = function () {
                    //2.svg转成canvas
                    var canvas        = document.createElement('canvas');  //准备空画布
                        canvas.width  = img.width;
                        canvas.height = img.height;
                    //取得画布的2d绘图上下文
                    var context = canvas.getContext('2d');
                        context.drawImage(img, 0, 0);
                    //3. 图片导出为 png 格式
                    var type    = 'png';
                    var imgData = canvas.toDataURL(type);

                    var _fixType = function (type) {
                        type  = type.toLowerCase().replace(/jpg/i, 'jpeg');
                        var r = type.match(/png|jpeg|bmp|gif/)[0];
                        return 'image/' + r;
                    };
                    // 加工image data,替换mime type
                    imgData = imgData.replace(_fixType(type), 'image/octet-stream');
                    if (extend && extend.canvasCallBack && typeof extend.canvasCallBack === 'function') {
                        that.tag('canvas创建成功');
                        extend.canvasCallBack(imgData);
                    }
                } 
            });
        }
    }
})();
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值