在项目开发中有一个需求,用户上传一个时间线的数据,通过选择不同的模板,将时间线数据可视化。用户保存这个文件时,将模板预览图截取作为文件的封面。
最终的结果就是把相应的DOM转换成一张图片传回后台。关键难点在于如何把DOM转换成图片。然鹅,最难搞定的那部分已经有了一个较为成熟的框架html2canvas。项目时间比较急迫,先使用第三方插件,自己封装canvas方法来截图的方案,后续再尝试一下。
const iframeHtml = this.$refs.timeLineDom.contentWindow // 获取iframe内容
const iframeBody = iframeHtml.document.getElementsByTagName('body')[0]
html2canvas(iframeBody).then(canvas => {
// 转成图片,生成图片地址
imgBase64 = canvas.toDataURL('image/png')
if (imgBase64) {
resolve(imgBase64)
} else {
reject(new Error('图片转换出错')
}
})
因为是保存文件时,执行的转换操作。我们要在图片成功转换成功后再进行保存操作。所以代码要稍微改造一下:
handleSaveImg () {
let imgBase64 = null
var iframeHtml = this.$refs.timeLineDom.contentWindow // 获取iframe内容
const iframeBody = iframeHtml.document.getElementsByTagName('body')[0]
return new Promise(function (resolve, reject) {
html2canvas(iframeBody).then(canvas => {
// 转成图片,生成图片地址
imgBase64 = canvas.toDataURL('image/png')
if (imgBase64) {
resolve(imgBase64)
} else {
reject(new Error(this.globleMessage.errorImgTransform))
}
})
})
},
搞定!看一下效果
。。。显然这有违初衷,图片太长导致压缩得根本看不出什么
再过一遍需求,我们最理想的效果是:预览窗口显示什么样子,封面的图片就应该是什么样子。
我们还需要做一些处理,即,拿到iframe里面模板滚动的距离,通过计算截取与预览窗口一样视图区域。
const iframeScrollY = iframeHtml.document.documentElement.scrollTop
const iframeScrollX = iframeHtml.document.documentElement.scrollLeft
html2canvas(iframeBody, {
allowTaint: true,
useCORS: true,
width: 812, // TODO 截屏按照1920*1080分辨率下的预览窗口宽高
height: 661,
x: iframeScrollX,
y: iframeScrollY
})
看一下效果
这样功能算是完成了。看看其他模板的效果:
预览图:
封面:
预览图2:
封面2:
handleSaveImg () {
let imgBase64 = null
var iframeHtml = this.$refs.timeLineDom.contentWindow // 获取iframe内容
const iframeBody = iframeHtml.document.getElementsByTagName('body')[0]
const iframeScrollY = iframeHtml.document.documentElement.scrollTop
const iframeScrollX = iframeHtml.document.documentElement.scrollLeft
return new Promise((resolve, reject) => {
html2canvas(iframeBody, {
allowTaint: true,
useCORS: true,
width: 812, // TODO 截屏按照1920*1080分辨率下的预览窗口宽高
height: 661,
x: iframeScrollX,
y: iframeScrollY
}).then(canvas => {
// 转成图片,生成图片地址
imgBase64 = canvas.toDataURL('image/png')
if (imgBase64) {
resolve(imgBase64)
} else {
reject(new Error(this.globleMessage.errorImgTransform))
}
})
})
},