解决html2canvas组件生成截图卡顿问题

2,604 阅读2分钟

h5端在开发的时候,难免有需要截图分享等功能,但是有时候又没有客户端app的支持,只能自己实现,而当下比较流行的元素截图也就是html2canvas和domtoimage

其中domtoimage存在致命的问题就是生成的截图会很模糊,如下图,左侧是domtoimage生成的,其原因大概是canvas中原像素因为没有与物理像素的统一导致其中原像素点与设备像素产生偏差,然后解决的方法网上一堆大概也就是修改node文件里的domtoimage包,使canvas适配设备宽高。但是要修改node包就这一点让很多联合开发的项目就很难实现,当然也可以用patch-package解决,这个我们以后再讲。

image.png

因为domtoimage存在以上截图模糊问题,我们自然而然的想到用html2canvas代替,html2canvas也不负众望,生成的图非常清晰,结构上也没什么问题(这是我以前一直用html2canvas的原因)。但是最近遇到一个问题,我在一个比较复杂的项目中使用时,生成图片非常慢(主要原因是生成过程会从html开始遍历,会遍历很多无用dom),甚至会高达10几秒,这是产品不能接受的,因此我搜了很多资料,大概就是使用参数ignoreElements

ignoreElementshtml2canvas.hertzen.com/configurati…

实现无用的dom过滤,但是都没有说清楚具体怎么实现和实现的代码,下面我提供下我的实现内容:

1、首先要保留截图元素的上下级

e.contains(element) 

element.contains(e) 

2、经过第一步后,速度会提升数倍,几乎秒开,但是会发现样式也被我们筛选掉了,因此得加上样式的过滤

e.tagName === 'STYLE' 

e.tagName === 'LINK' 

3、经过第二步,其实发现样式还是没有,主要原因是样式都在header里,而第一步过滤了header,因此我们要在herder上加data-html2canvas属性,同时在方法里过滤

e.getAttribute('data-html2canvas') != null

到此,我们就完成了截图的完美生成,速度快的一批,直接甩产品脸上,让他哑口无言,下面是具体实现的代码:

html2canvas(element, {
          useCORS: true,
          ignoreElements: e => {
            if (
              e.contains(element) ||
              element.contains(e) ||
              e.tagName === 'STYLE' ||
              e.tagName === 'LINK' ||
              e.getAttribute('data-html2canvas') != null // header里面的样式不能筛掉
            ) {
              console.log(e);
              return false;
            }
            // console.log(e.tagName);
            return true;
          }
        })
          .then(canvas => {
            const dataUrl = canvas.toDataURL('image/jpeg'); // 得到base64
            console.log('2222244444444444', dataUrl);
            window.JSSDK.wxShare({
              scene: 0,
              type: 1,
              title: `${name || '--'}(${code || '--'})`,
              share_content: '让财富管理更轻松',
              link: `${window.location.href}&share=1`,
              imgData: dataUrl.split(',')[1]
            });
          })
          .catch(function (error) {
            console.log('22222', error);
          });