场景:
项目需要做一个以HTML作为模板的预览列表,预览列表通过截图的方式进行显示,类似于图片的缩略图。
那为什么不直接使用html解析的方式放置在固定的容器内呢?
容器会对HTML进行解析,例如200px的空间内显示600px宽的html原始页面,显示的布局会被压缩,不是按比例进行解析,至于是否有CSS可以控制HTML,进行类似图片可以按照比例进行显示,没有找到什么好的办法。
查了一些资料都是对本页面进行截图,如果需要结合VUE截图的资料也比较少,主要是涉及到一些对象的取值和设置,费了一些周折。
一、首先按照官方的文档进行安装
二、新建个html截图组件
命名为:html-capture.vue
<template>
<!--<img :src="imgUrl"/>-->
<!--这里使用的ElementUI的组件,可换成普通的图片标签-->
<el-image :src="imgUrl" fit="scale-down" :preview-src-list="srcList">
<!--preview-src-list 用来点击预览图片 --> </el-image>
</template>
<script>
import html2canvas from 'html2canvas'
import HtmlPanel from '@/components/html-panel'
export default {
name: 'HtmlCapture',
components: {
html2canvas
},
props: {
htmlUrl: {
required: true
},
width: String,
height: String,
src: String
},
data () {
return {
imgUrl: '',
srcList: []
}
},
methods: {
// html截图 ,v 将Vue对象传递进方法,截图方法内无法获取Vue的this对象
htmlToImg (v) {
// 通过创建临时的iframe动态加载页面 实现通过url获取dom
var iframe = document.createElement('iframe')
iframe.ref = 'htmlLoadFrame' iframe.src = this.htmlUrl
// 隐藏临时iframe
document.body.appendChild(iframe)
iframe.style.cssText = 'position: absolute; opacity:0; z-index: -9999'
// iframe加载完成后触发
iframe.onload = function (e) {
// 生成iframe中的页面截图
html2canvas(iframe.contentDocument.documentElement, {
// 设置截图的背景色,设置为白色背景,预览时不是透明图片
backgroundColor: 'white',
// 如果截图的内容里有图片,可能会有跨域的情况,加上这个参数,解决文件跨域问题
useCORS: true,
// 允许跨域(图片跨域相关)
allowTaint: true,
// 是否在渲染前测试图片
taintTest: true,
// 放大倍数,4倍相对文字比较清晰
scale: 4,
// 设置图片的宽度
windowWidth: iframe.contentDocument.documentElement.clientWidth * 2,
width: iframe.contentDocument.documentElement.clientWidth * 2
}).then((canvas) => {
// 转换为Base64,将base64赋值给data中的imgUrl变量
// 通过参数传递的Vue对象设置变量值,此处无法直接操作Vue this对象
v.imgUrl = canvas.toDataURL('image/png')
// 赋值给ElementUI预览图片时需要的数组
v.srcList.push(v.imgUrl)
// 截图完成后销毁iframe
iframe.remove()
})
}
}
},
mounted () {
this.htmlToImg(this)
}}
</script>
<style>
</style>三、使用组件
<template>
<div v-for="el in elData">
<el-card class="box-card" style="height:300px" shadow="hover">
<html-capture :htmlUrl="el.url" style="width:100%"></html-capture>
</el-card>
</div>
</template>
<script>
import HtmlCapture from '@/components/html-capture'
export default {
name: 'HtmlCaptureExample'
components: {
HtmlCapture
},
data () {
return {
elData: [
{url: '/static/html/test1.html'},
{url: '/static/html/test2.html'}, {url: '/static/html/test3.html'}
]
}
}
}大部分网站是不允许跨域的,因此测试还是使用自己本地页面
效果如下图
官网也提到不是所有的CSS都支持,不过一般对于模板展示类的需求还是可以满足。