目录

前言

一、准备

二、解决问题

1.将svg跟img转为canvas的方法

2.将base64转换成file文件的方法

3.点击下载使用方法

1).对dom没有处理,需求只是将图片导出即可

2).涉及对dom的拖拽,流程图之类的(需复制dom,在复制的dom上进行处理)

三、效果图如下


前言

查阅很多相关的文章和文档,大多是解决svg导出不显示的问题,这个还是比较好处理的。但是对于我的需求而言,主要问题是,需要导出成图片的dom元素,中间既有img又有svg,导致我在导出时,img的元素并没有显示在导出的图片上

一、准备

我使用的html2canvas版本是1.4.1 ,canvg版本是1.5.3

npm install --save html2canvas@1.4.1npm install --save canvg@1.5.3

引入组件

import html2canvas from "html2canvas";import canvg from "canvg";

二、解决问题

1.将svg跟img转为canvas的方法

changeToCanvas(element) {const svgElems = element.querySelectorAll('svg');const imgElems = element.querySelectorAll('img');//es6语法let elems = [...svgElems, ...imgElems]elems.forEach(node => {let parentNode = node.parentNode;let canvas = document.createElement("canvas");canvas.style.zIndex = 9//处理svg转换canvas需要使用canvg组件if (node.tagName == 'svg') {let svg = node.outerHTML.trim();canvg(canvas, svg);if (node.style.position) {canvas.style.position += node.style.position;canvas.style.left += node.style.left;canvas.style.top += node.style.top;}} //处理img转换canvasif (node.tagName == 'IMG') {canvas.width = node.width;canvas.height = node.height;canvas.getContext("2d").drawImage(node, 0, 0)}parentNode.removeChild(node);parentNode.appendChild(canvas);});}

2.将base64转换成file文件的方法

base64ToFile(dataurl) {let arr = dataurl.split(',');let mime = arr[0].match(/:(.*?);/)[1];let bstr = atob(arr[1]);let n = bstr.length;let u8arr = new Uint8Array(n);while (n--) {u8arr[n] = bstr.charCodeAt(n);}return new Blob([u8arr], {type: mime});},

3.点击下载使用方法

downloadIMG()这个方法中,由于我是svg制作流程图,避免下载后导致无法拖拽svg,所以我这里的做法是先复制一个临时元素,在使用完后再清除掉,如果说你本身不对svg以及img做一些操作的话,可以不需要这几步。

scale属性可以解决解决生成的canvas模糊问题

1).对dom没有处理,需求只是将图片导出即可

downloadIMG() {//需要在id为flowWrap的div里面加上 ref="flowWrap"const flow = this.$refs.flowWrapflow.style.background = '#000'//调用changeToCanvasthis.changeToCanvas(flow)html2canvas(flow, {taintTest: false,scale: window.devicePixelRatio  {//调用base64ToFilelet blob = this.base64ToFile(canvas.toDataURL('image/png'));let a = document.createElement('a');a.setAttribute('href', URL.createObjectURL(blob));a.setAttribute('download', new Date().getTime() + '.png');URL.revokeObjectURL(blob);a.click();a.remove();//element组件,你可以直接使用alert查看this.$message.success('生成成功')}).catch((error) => {//element组件,你可以直接使用alert查看this.$message.error('生成失败,请查看控制台错误')});},

2).涉及对dom的拖拽,流程图之类的(需复制dom,在复制的dom上进行处理)

downloadIMG() {//找到元素dom并复制一个临时元素(需要在id为flowWrap的div里面加上 ref="flowWrap")//我这里id为flowWrap,你需要替换为你的idconst flow = this.$refs.flowWrap//svg转换canvas会导致svg无法拖动,使用临时元素const tmpFlow = flow.cloneNode(1)tmpFlow.style.background = '#000'flow.appendChild(tmpFlow)//调用changeToCanvasthis.changeToCanvas(tmpFlow)html2canvas(tmpFlow, {taintTest: false,scale: window.devicePixelRatio  {//调用base64ToFilelet blob = this.base64ToFile(canvas.toDataURL('image/png'));let a = document.createElement('a');a.setAttribute('href', URL.createObjectURL(blob));a.setAttribute('download', new Date().getTime() + '.png');URL.revokeObjectURL(blob);a.click();a.remove();flow.removeChild(tmpFlow) // 移除临时tmpFlow//element组件,你可以直接使用alert查看this.$message.success('生成成功')}).catch((error) => {flow.removeChild(tmpFlow) // 移除临时tmpFlow//element组件,你可以直接使用alert查看this.$message.error('生成失败,请查看控制台错误')});},

三、效果图如下