使用VFD流程设计器图片下载问题 利用html2canvas处理svg生成canvas,之后在利用canvas转成base64进行图片展示
使用html2canvas对svg线条没有显示问题,
实际画出的流程图为
文章图片
但是点击生成流程图片的时候线条却不见了
文章图片
【js|jsPlumb使用html2canvas无法识别svg】原因是因为利用html2canvas处理svg成canvas时是异步进行,还没有生成出来就画canvas肯定就没有了呀
解决办法
这个是点击生成图片的方法 VFD流程设计器的图片生成的源码解析
exportFlowPicture () {
const that = this;
// 获取节点VFD流程编辑器里面画的节点
let $Container = that.$refs.flowArea.$el.children[0]
// 获取线条放进数组
let svgElems = $($Container).find('svg[id^="link-"]')
let removeArr = [];
svgElems.each(function(index, svgElem) {
// 创建canvas
let linkCanvas = document.createElement('canvas');
// 设置canvas的id,可自行设置
let canvasId = 'linkCanvas-' + ZFSN.getId();
linkCanvas.id = canvasId;
removeArr.push(canvasId);
// 获取线条转成字符串
let svgContent = svgElem.outerHTML.trim();
// 利用canvg处理svg转png 注意这里canvg的插件是2.0.0版本。其他版本可能不是这样的用法
canvg(linkCanvas, svgContent)
//设置线条的位置,保证跟画的流程节点位置一致
if (svgElem.style.position) {
linkCanvas.style.position += svgElem.style.position;
linkCanvas.style.left += svgElem.style.left;
linkCanvas.style.top += svgElem.style.top;
}
// 把生成的canvas线条放进$Container里
$($Container).append(linkCanvas);
});
// 这个方法是生成图片(节点)的位置大小
let canvasSize = that.computeCanvasSize();
let pbd = flowConfig.defaultStyle.photoBlankDistance;
let offsetPbd = ZFSN.div(pbd, 2);
html2canvas($Container, {
width: canvasSize.width + pbd,
height: canvasSize.height + pbd,
scrollX: -canvasSize.minX + offsetPbd,
scrollY: -canvasSize.minY + offsetPbd,
logging: false,
onclone: function(args) {
removeArr.forEach(function(id, index) {
//删除前面添加的canvas节点
$('#' + id).remove();
});
}
}).then(canvas => {
let dataURL = canvas.toDataURL('image/png');
that.flowPicture.url = dataURL;
that.flowPicture.modalVisible = true;
});
},
computeCanvasSize () {
const that = this;
//流程画的节点数据
let nodeList = Object.assign([], that.flowData.nodeList),
minX = nodeList[0].x,
minY = nodeList[0].y,
maxX = nodeList[0].x + nodeList[0].width,
maxY = nodeList[0].y + nodeList[0].height;
nodeList.forEach(function(node, index) {
minX = Math.min(minX, node.x);
minY = Math.min(minY, node.y);
maxX = Math.max(maxX, node.x + node.width);
maxY = Math.max(maxY, node.y + node.height);
});
let canvasWidth = maxX - minX;
let canvasHeight = maxY - minY;
return {
width: canvasWidth,
height: canvasHeight,
minX: minX,
minY: minY,
maxX: maxX,
maxY: maxY
};
},
下面是对图片线条无法展示使的改进,利用Promise实现
exportFlowPicture () {
const that = this;
// 获取节点VFD流程编辑器里面画的节点
let $Container = that.$refs.flowArea.$el.children[0]
// 获取线条放进数组
let svgElems = $($Container).find('svg[id^="link-"]')
let removeArr = [];
const callback = []
svgElems.each(function(index, svgElem) {
// 创建canvas
let linkCanvas = document.createElement('canvas');
// 设置canvas的id,可自行设置
let canvasId = 'linkCanvas-' + ZFSN.getId();
linkCanvas.id = canvasId;
removeArr.push(canvasId);
// 获取线条转成字符串
let svgContent = svgElem.outerHTML.trim();
//设置线条的位置,保证跟画的流程节点位置一致
if (svgElem.style.position) {
linkCanvas.style.position += svgElem.style.position;
linkCanvas.style.left += svgElem.style.left;
linkCanvas.style.top += svgElem.style.top;
}
//设置画布大小跟真实线条一样大小
linkCanvas.width = svgElem.width.animVal.value
linkCanvas.height= svgElem.height.animVal.value
//利用promise实现异步(改动的地方(核心))
let promiseType = new Promise((resole,reject)=>{
// 把这个放进promise就好
canvg(linkCanvas, svgContent)
// 把生成的canvas线条放进$Container里
$($Container).append(linkCanvas);
resole()
})
//把生成的promise放进callback数组里
callback.push(promiseType )
});
// 利用Promise的all方法,当所有的都成功画出来的时候才执行生成总的canvas生成
Promise.all(callback).then(()=>{
// 这个方法是生成图片(节点)的位置大小
let canvasSize = that.computeCanvasSize();
// let pbd = flowConfig.defaultStyle.photoBlankDistance;
// let offsetPbd = ZFSN.div(pbd, 2);
html2canvas($Container, {
//width: canvasSize.width + pbd,
//height: canvasSize.height + pbd,
//scrollX: -canvasSize.minX + offsetPbd,
//scrollY: -canvasSize.minY + offsetPbd,
width: canvasSize.width,
height: canvasSize.height,
scrollX: -canvasSize.minX,
scrollY: -canvasSize.minY
logging: false,
onclone: function(args) {
removeArr.forEach(function(id, index) {
//删除前面添加的canvas节点
$('#' + id).remove();
});
}
}).then(canvas => {
let dataURL = canvas.toDataURL('image/png');
that.flowPicture.url = dataURL;
that.flowPicture.modalVisible = true;
});
})
},
推荐阅读
- html|浏览器打印解决input框内容无法获取值得问题 print()
- 利用js写一个倒计时器
- javascript|微信H5页面前端开发,大多数人都会遇到的几个兼容性坑
- 前端|前端中一些数值类型的输出结果
- p2p|芜湖,这是一棵会唱歌的圣诞树
- javascript|JavaScript脚本语言介绍并实现第一个Hello World程序
- 前端|JavaScript 存储对象 -sessionStorage (会话存储) 和 localStorage(本地存储)以及 cookie(保存用户信息) 的区别
- css|如何在Chrome浏览器中运行Selenium()
- html|纪念计算机之父阿兰·图灵诞辰109周年