使用html2canvas、jQuery结合Canvg绘制canvas图并下载
需求如下:
这是一个画布,使用jsPlumb绘制图进行连线,现在需要点击下载的按钮将这个画布上绘制的图保存到本地。节点是使用svg绘制的,线是使用jsPlumb绘制的,因此需要重新绘制成canvas。在整个需求完成的过程中遇到了以下几个问题:
1、需要区分节点svg和线,线需要使用canvas重新绘图,节点不需要
2、绘制完成之后如何下载到本地
3、下载并保存到本地的功能实现之后发现,下载成功之后去移动节点,连线会进行错乱。像如下这样
直接附上代码,具体实现都在代码中注释了
// 保存图片
saveChartImg () {
// flowContent是画布的容器
var statemachinediv = document.getElementById("flowContent");
// 获取并遍历所有的svg
var svgList = $(statemachinediv).find("svg");
svgList.each(function (index, value) {
try {
var svgExample = this;
var serializer = new XMLSerializer();
// XMLSerializer.serializeToString() 把一个 XML 文档或节点转换为一个字符串
var svgMarkup = serializer.serializeToString(svgExample);
// 线的位置都是有定位的,因此根据是否有定位判断是否为连线
if (value.style.position) {
var parentNode = value.parentNode;
let svg = value.outerHTML.trim();
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
let v = Canvg.fromString(ctx, svgMarkup);
v.start();
canvas.style.position += value.style.position;
canvas.style.left += value.style.left;
canvas.style.top += value.style.top;
// 将绘制的canvas的线加入到DOM元素中
parentNode.appendChild(canvas);
}
} catch (err) {
console.log("error in print: " + err);
}
});
const canvas = document.createElement("canvas");
// canvas width
canvas.width = obj.width.substring(0, obj.width.length - 2) * 1;
// canvas height
canvas.height = obj.height.substring(0, obj.height.length - 2) * 1;
// 这里使用html2canvas将所有的绘制成一张canvas图
html2canvas(statemachinediv, {
width: canvas.width,
canvas: canvas,
heigth: canvas.height,
useCORS: true // Enable cross-domain configuration
}).then(canvas => {
let that = this
// 这句话加上之后,下载完成之后画布上会多出来一份绘制的canvas
// statemachinediv.appendChild(canvas);
var image = canvas
.toDataURL("image/png")
.replace("image/png", "image/octet-stream");
var saveFile = function (data, filename) {
let _that = that
var save_link = document.createElementNS(
"http://www.w3.org/1999/xhtml",
"a"
);
save_link.href = data;
save_link.download = filename;
var event = document.createEvent("MouseEvents");
event.initMouseEvent(
"click",
true,
false,
window,
0,
0,
0,
0,
0,
false,
false,
false,
false,
0,
null
);
save_link.dispatchEvent(event);
_that.clearDom()
};
// // 下载后的问题名
var filename = "下载.png";
// download
saveFile(image, filename);
});
},
// 清除DOM元素中无用的元素
// 这里就是为了解决上面的第三个问题,是为了将绘制添加进去的连线的canvas给从DOM元素中去除,否则每条线都会有重复的一条,出现错乱的情况
clearDom () {
var domFlowChange = document.getElementById("flowContent");
var canvasList = $(domFlowChange).find("canvas");
canvasList.each(function (index, value) {
try {
var can = this
let parentNode2 = value.parentNode;
parentNode2.removeChild(value);
} catch (err) {
console.log("error in print: " + err);
}
});
},
感谢这篇文章,对于dom的操作给了一定的提示。
JS删除DOM元素的两种方法
这里是文章中的内容: