html2canvas 图片模糊研究及规避方法

本文探讨了html2canvas截图模糊问题,提出三种优化方法:1) 改变元素宽高;2) 使用transform: scale;3) 设置html2canvas的scale参数。方法1效果最佳,但成本高;方法3适用于一般需求。在高清晰度场景下,三种方法结合使用。文章还介绍了完整代码示例和注意事项,包括图片大小控制和文字位移规避。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Html2canvas 图片模糊,可能的三种处理方法:

1、修改元素的宽高像素。 如果元素及其子元素的宽高变大了,截出的图片也会更大,更清晰。特别是对img或者带背景图的元素,其清晰度和原始宽高像素值直接相关。如果把图片元素的宽高放大并设置transform scale缩小,图片在页面的显示效果不变,但截图时图片分辨率会提高。

2、修改元素的transform: scale(2) 让截图根元素放大,并让截出的图片变大。大图片自动缩小后看,会显得清晰。但是在一些细节,比如文字阴影的偏移方面,显示会有偏差,没有进行相应的缩放。

      let start = () => {
        $('#rootNode').css('transform', ‘scale(2)'); // 截图时放大
      };
      let end = () => {
        $('#rootNode').css('transform', ‘scale(.5)); // 截图后恢复
      };

3、html2canvas 的scale参数。这个效果上和方法2基本没有区别。scale参数默认值为 window.devicePixelRatio, mac的视网膜屏上,默认是2了(如果为1, 在视网膜屏幕上会糊),所以mac图片的像素大小是windows图片的2倍。如果要让截出的图大小统一,可以统一设置为2。

上述3种方法,1是最好的,特别是需要提高嵌入的图片的分辨率的时候。2,3差不多,但是3的细节方面要稳定些(比如文字阴影)。

综合来说, 效果 是 1 >2 >3, 实现成本是1 > 2 = 3。

要求不高的场合, 方法3足够好。

清晰度要求高的场合,需要三者结合:

A. 先采用1, 以放大2倍的方式,绘制需要截图的根元素下所有dom元素的宽高。并通过transform: scale(.5)缩小元素,在页面正常显示。这一步也可以不是2倍,而是其他倍数。

B. 截图前采用2,将transform scale(.5)移除, 恢复默认的2倍大小,同时可以规避html2canvas在处理transform过的元素时的各种bug和限制(如阴影偏移)。

C. 最后采用3,设置比例,调整最终的截图大小。

完整代码:


    svgToImage(node){
      // 截图前
      let start = () => {
        $(node).css('transform', ''); // 相当于scale(1)

        // 截图时文字偏下修正
        $('.editable').each( function () {
          let $this = $(this);
          var paddingTop = +$(this).css('paddingTop').split('px')[0];
          $(this).css('paddingTop', paddingTop - 10 + 'px');
        });
      };
      // 截图后
      let end = () => {
        $(node).css('transform', 'scale(.5)'); // 页面中默认scale

        // 恢复文字偏下修正
        $('.editable').each(function () {
          let $this = $(this);
          var paddingTop = +$(this).css('paddingTop').split('px')[0];
          $(this).css('paddingTop', paddingTop + 10 + 'px');
        });
      };
      start();
      html2canvas(node, {
        scale: 2 * .8,  // scale 参数
        allowTaint: true,
        useCORS: true
        // foreignObjectRendering: true
      }).then(canvas => {
        
        // 缩小成想要的比例
        const w = 900;
        const h = 383;
        const elem = document.createElement('canvas');
        elem.width = w;
        elem.height = h;
        const ctx = elem.getContext('2d');
        ctx.imageSmoothingEnabled = true;
        ctx.imageSmoothingQuality = "high";
        ctx.drawImage(canvas, 0, 0, w, h);
        canvas = elem;

        var b64;
        try {
          b64 = canvas.toDataURL("image/png");
        } catch (err) {
          console.log(err);
          end();
          alert(err);
        }
       
        var a = document.createElement("a");
        a.href = b64;
        a.download = 'poster.png'; //设定下载名称 
        var evt = document.createEvent("MouseEvents");
        evt.initEvent("click", true, true);
        a.dispatchEvent(evt);
        end();
      });
    }
如果要对最终图片的大小有明确要求,可以用上述3种方法将图片放大,然后再利用下述代码缩小。其中用到了imageSmoothingQuality属性,缩小后效果更平滑。注意这个办法更适合缩小而不适合放大,用这个方法放大的清晰度不如上述3种方法的结合。
        // 缩小成想要的比例
        const w = 900;
        const h = 383;

        const elem = document.createElement('canvas');
        elem.width = w;
        elem.height = h;
        const ctx = elem.getContext('2d');
        ctx.imageSmoothingQuality = "high”;
        ctx.drawImage(canvas, 0, 0, w, h);  // canvas为html2canvas导出的canvas
        canvas = elem;    // 用elem 替换原来的 canvas
截图中文字有时会有位移,偏下。可以用下述方法规避。 start为截图前的函数, end为截图后。
      let start = () => {
        // 截图时文字会偏下,所以先调成偏上
        $('.editable').each( function () {
          let $this = $(this);
          var paddingTop = +$(this).css('paddingTop').split('px')[0];
          $(this).css('paddingTop', paddingTop - 10 + 'px');
        });
      };
      let end = () => {
        // 恢复修正
        $('.editable').each(function () {
          let $this = $(this);
          var paddingTop = +$(this).css('paddingTop').split('px')[0];
          $(this).css('paddingTop', paddingTop + 10 + 'px');
        });
      };
html2canvas 原理和不支持的属性说明

The script traverses through the DOM of the page it is loaded on. It gathers information on all the elements there, which it then uses to build a representation of the page. In other words, it does not actually take a screenshot of the page, but builds a representation of it based on the properties it reads from the DOM.

As a result, it is only able to render correctly properties that it understands, meaning there are many CSS properties which do not work. For a full list of supported CSS properties, check out the supported features page.

不支持属性列表 尤其注意svg图片作为背景时,很可能出现乱码。尽量不要使用svg图片。

图片太大会影响性能,建议控制在1920 * 1080像素以内。

本文写作时用到的html2canvas版本是 1.0.0-rc.5, 相信随着越来越多的bug修正和特性完善,html2canvas的使用体验会越来越完善,不用再这么大费周折。
错误再所难免,希望大家指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值