需求如下:
对展示的图表数据(热力图)进行截图,并转成base64格式传给后台。
每个图表框架都带有下载的API接口,plotly如下:
Plotly.newPlot(DOM元素的ID, 图表数据, 图表配置, 参数).then(function(res) {
/* 手动触发下载事件 */
Plotly.downloadImage(res, {
// 画完时,自动将图保存成png格式的图片
format: 'png',
height: 500,
width: 1000,
filename: '名称'
})
});
很可惜,我没法进行拦截,获取不到图片数据,最终结果是图片会被直接下载到本地。
我想到了使用第三方库的方式来进行截图,比如:
- html2canvas(canvas截图)
import html2canvas from 'html2canvas'
html2canvas(this.$refs.colormap).then(canvas => {
return canvas.toDataURL('image/png')
})
发现图是可以截的,但是图中的某些样式(比如图元颜色)会丢失,最终的图片并不符合我的要求。
后面发现,plotly是基于svg底层实现的,所以后续使用了另一个库:
- rasterizehtml(svg截图)
const opts = {
height: '530',
width: '1500'
}
rasterizehtml.drawDocument(this.$refs.colormap, null, opts).then(async(data) => {
console.log(data)
})
获取的数据如下:
属性svg中就是我们最终的图,直接复制,找一个在线编辑器验证(比如菜鸟教程),发现这回样式没丢,但是原本一个图中的两个图元被分成了两个不同的图,也不符合要求。
后续查看属性svg中的代码,外加查询了一些资料参考,比如:
将svg属性的字符串进行了调整,把所有图元都放在了一个svg标签下面,图片就是我所需要的。
这时候,又有一个问题,svg属性内的字符串后台并不接受,我需要转成base64格式的。
于是,又参考了许多资料后
// svg节点(DOM)转Base64
function svgToCanvas(node, params = { width: '1500', height: '530' }) {
return new Promise((resolve) => {
const s = new XMLSerializer().serializeToString(node)
const src = `data:image/svg+xml;base64,${window.btoa(s)}`
// 创建图片容器并存放
const img = new Image() // 创建图片容器
img.src = src
// 注意:需要在图片onload方法中执行
img.onload = () => {
const canvas = document.createElement('canvas')
canvas.width = params.width
canvas.height = params.height
const context = canvas.getContext('2d')
context.drawImage(img, 0, 0)
const base64 = canvas.toDataURL('image/png')
resolve(base64)
}
})
}