遇到的问题
在项目开发中有一个需求,用户上传一个时间线的数据,通过选择不同的模板,将时间线数据可视化。用户保存这个文件时,将模板预览图截取作为文件的封面。
实现的思路
最终的结果就是把相应的DOM转换成一张图片传回后台。关键难点在于如何把DOM转换成图片。然鹅,最难搞定的那部分已经有了一个较为成熟的框架html2canvas。项目时间比较急迫,先使用第三方插件,自己封装canvas方法来截图的方案,后续再尝试一下。
- 获取iframe的dom结构
- 将获取到的dom直接传给html2canvas,转换canvas
- 调用toDataURL将canvas转换成图片base64格式
html

页面展示

实现步骤
- 获取iframe的dom结构
const iframeHtml = this.$refs.timeLineDom.contentWindow // 获取iframe内容
const iframeBody = iframeHtml.document.getElementsByTagName('body')[0]
- 将dom转换成canvas,并转换成base64
imgBase64就是截取到的图片,格式是base64
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里面模板滚动的距离,通过计算截取与预览窗口一样视图区域。
- 获取iframe滚动的距离
const iframeScrollY = iframeHtml.document.documentElement.scrollTop
const iframeScrollX = iframeHtml.document.documentElement.scrollLeft
- 将滚动的距离和要截取的宽高传给html2canvas
html2canvas(iframeBody, {
allowTaint: true,
useCORS: true,
width: 812, // TODO 截屏按照1920*1080分辨率下的预览窗口宽高
height: 661,
x: iframeScrollX,
y: iframeScrollY
})
看一下效果
这样功能算是完成了。看看其他模板的效果:
预览图:
封面:
预览图2:
封面2:
预览图3:
封面3:
最终代码
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))
}
})
})
},
版权声明:本文为weixin_43831691原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。