一、安装插件

npm install html2canvas

npm install canvg

html2canvas 将页面保存在canvas进行图片保存 

canvg 将页面中的svg转化为canvas

1、关于canvg

1.1 启动canvg引擎

  • new Canvg(...)
  • Canvg.from(...)
  • Canvg.fromString(...)

from和fromString的区别是from需要传入的是svg本身,而fromString需要传入的是svg的字符串形式。这三种方式都可以传入三个参数,第一个参数是canvas画布的绘制上下文,第二个是需要绘制的svg,第三个是自定义配置选项,可以用于控制画布的渲染结果。

1.2 canvg启动渲染的方法有两种:renderstart

区别是当需要绘制的svg是动态图时,render只会绘制第一帧的内容,也就是说绘制出来的图像是静态的,而start是会将svg的内容以及动效全部都绘制出来,也就是说图片是动态的形式。

二、引入插件

import html2canvas from 'html2canvas';

import { Canvg } from 'canvg'

三、使用

<div class="svg-box">

    <svg class='svg' width="100%" height="100%" viewBox="0 0 200 200" ref="svg">
              
       <!-- 外圈圆 -->
       <circle cx="100" cy="100" r="90" stroke="#dcdcdc" stroke-width="10" fill="none" />

       <!-- 内圈圆,虚线用于展示进度 -->
       <circle cx="100" cy="100" r="90" stroke="#ff0000" stroke-width="10" fill="none" :stroke-dasharray="Math.PI*45 +','+ 2*Math.PI*90" :stroke-dashoffset="0" stroke-linecap="round" transform="rotate(-90,100,100)"></circle>
              
    </svg>
            
</div>
this.$nextTick(async () => {
      
      const parentNode = this.$refs.svg.parentNode;
      const svg = this.$refs.svg.outerHTML.trim();
    
      let canvasDom = document.createElement('canvas')
      let ctx = canvasDom.getContext('2d')
      canvasDom.setAttribute('width', this.$refs.svg.clientWidth+'px')
      canvasDom.setAttribute('height', this.$refs.svg.clientHeight+'px')
      canvasDom.setAttribute('style', 'display:block;')

      document.body.appendChild(canvasDom)

      const v = Canvg.fromString(ctx, svg);
      await v.render();
    
      parentNode.removeChild(this.$refs.svg);
      parentNode.appendChild(canvasDom);


      html2canvas(this.$refs.imgDom, {
            useCORS: true // 允许CORS跨域
      }).then((canvas) => {
        this.imgUrl = canvas.toDataURL("image/png")
        
        // 触发图片下载
        const aElem = document.createElement('a')
        document.body.appendChild(aElem)
        aElem.href = this.imgUrl
        // 设置下载标题
        aElem.download = "chart.jpg"
        aElem.click()
        document.body.removeChild(aElem)
      });
      
})

四、兼容问题

1.背景图片模糊
解决方案:使用img标签来实现background-image的效果

2.图片无法渲染
在img标签内加入crossorigin=‘anonymous’(crossorigin='anonymous’可以触发带跨域请求头Origin的HTTP请求)并给html2canvas设置allowTaint: true配置

3.跨域加载的图片会污染canvas,进而导致canvas无法导出数据

解决方案1:给html2canvas设置useCORS:true加载跨域图像的配置,并且保证给每个图片添加添加crossOrigin="anonymous"属性


解决方案2:将文件读入到blob文件对象,然后用URL.createObjectURL()方法转换成img src可用的地址,然后再转canvas


注意:读入blob文件时保证要设置的img标签内的src为空,在读入文件完成后在调用生成图片函数 

// 将文件读入到blob文件在转img的方法
function getImage ( url ) {
    const xhr = new XMLHttpRequest();
    xhr.open('get', url, true);
    xhr.responseType = 'blob';
    xhr.onload = function () {
        if (this.status == 200) {
            this.imgUrl =  URL.createObjectURL(this.response);
        }
    };
    xhr.send();
    
}

let urltest = '跨域图片链接'

getImage(urltest,'test-img')

 

Logo

前往低代码交流专区

更多推荐