目录
前言
一、准备
二、解决问题
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('生成失败,请查看控制台错误')});},