dom-to-image 将vue中未显示的组件转成图片, 并上传
1、基本使用npm地址import domtoimage from 'dom-to-image'export function dom2img(node) {return domtoimage.toPng(node, { cacheBust: true }).then(function(dataUrl) {var img = new Image();img.src = dataUrl;docume
目录
一、dom-to-image基本使用
import domtoimage from 'dom-to-image'
export function dom2img(node) {
return domtoimage.toPng(node, { cacheBust: true })
.then(function(dataUrl) {
var img = new Image();
img.src = dataUrl;
document.body.appendChild(img);
return dataUrl
})
.catch(function(error) {
console.error('oops, dom2img went wrong!', error);
});
}
// 实现将dom转成图片
// node: this.$refs.id 或者 document.getElementById('id')
dom2img(node).then(img => {
// 处理base64格式的img
}
可以添加参数 , 比如控制大小,修改样式
domtoimage.toJpeg(node, {
width: 330,
height: 155,
cacheBust: true,
style: {
margin: 0,
background: '#fff',
}
})
二、注意点
dom-to-image
将dom转图片有个前提,就是一定要在文档中显示,任何样式导致不显示都导致无法生成图片,比如:visibility:hidden,display: none;
宽高不能是100%,否则也是转换失败
如果是动态引入的组件转换,要保证组件没有需要异步加载的部分,比如一些背景图是请求接口的, 只能在页面显示后,通过$refs来获取dom,动态引入不知道什么时候加载完成的
toPng 要去掉dom样式中的margin,否则切图出来的会有被截断的问题
三、生成的图片上传至服务器
平时上传图片主要是用到<input>
元素, 用户选择的文件最终是File对象,所以,我们将生成的图片转成File对象,然后通过formData上传即可。
这里主要用png格式和blob格式举例
1、base64 转 File 格式
function base64toFile(dataUrl, fileName = 'image') {
let arr = dataUrl.split(',')
let mime = arr[0].match(/:(.*?);/)[1]
let bstr = window.atob(arr[1]) // base64编码
let n = bstr.length
let u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n) // unicode 编码
}
return new File([u8arr], `${fileName}.png`, {
type: mime
})
}
2、blob 转 File 格式
File继承自Blob,是特殊类型的 Blob。
function blobtoFile(blob, fileName = 'image') {
const file = new File([blob], fileName, {
type: blob.type
})
return file
}
3、在页面展示生成的图片
function showImg(dataUrl) {
var img = new Image()
img.src = dataUrl
document.body.appendChild(img)
}
4、最终dom转图片函数
// XXX domtoimage 转图片有个前提,一定要在文档中显示,任何样式导致不显示都导致无法生成图片
// toPng(node, {width: 330, height: 155, quality: 0.95 }), 可以添加参数
// toPng 要去掉dom样式中的margin, 否则切图会有问题
import domtoimage from 'dom-to-image'
export function dom2img(node, fnType = 'toPng') {
return domtoimage[fnType](node, {
cacheBust: true
})
.then(function(dataUrl) {
// png
if (fnType === 'toPng') {
// 显示图片
showImg(dataUrl)
// 生成file格式用于上传
return base64toFile(dataUrl)
}
// blob
if (fnType === 'toBlob') {
// 显示图片: 通过Blob Url,blob://模式类似于http://,
const blobUrl = URL.createObjectURL(dataUrl)
showImg(blobUrl)
// 防止内存溢出,要手动释放
setTimeout(() => {
URL.revokeObjectURL(blobUrl)
}, 200)
// 生成file格式用于上传, 这个有问题,接口报错-- FIXME
return blobtoFile(dataUrl)
}
return dataUrl
})
.catch(function(error) {
console.error('oops, dom2img went wrong!', error)
})
}
5、上传图片
function uploadImgToBoot(imgFile) {
const formData = new FormData();
formData.append('file', imgFile)
return uploadZhImg(formData).then(res => {
return res
})
}
6、问题未解决
blob转File后,上传图片接口报错, 未找到原因
四、vue实现将不显示的组件转成图片,而组件之间出现循环引用
1、首先在html中放一个占位div,用于渲染dom
<!-- 用于挂载占位,不需要显示-->
<div id="hideNode" class="show-in-back"></div>
// 不能使用visibility:hidden 或者 display:none, 会导致dom转换失败
.show-in-back {
position: absolute;
top: 0;
z-index: -1000;
}
2、这里使用动态引入避免组件死循环:
// XXX 可以使用这种动态引入的前提是: 组件没有需要异步加载的部分,比如合集中的背景图是请求接口的, 只能通过$refs来
// 动态引入组件,避免组件之间出现循环引入,当出现死循环时,import的结果为undefined
const ApplyCard = () => import('@/views/apply/components/ApplyCard.vue')
这里有两种vue的引入方式: 模板编译和runtime模式
// 默认runtime模式,指向了"dist/vue.runtime.common.js"位置
import Vue from 'vue'
// 下面引入采用的是模板编译引入链接
// import Vue from 'vue/dist/vue.esm.js'
3、挂载点内容会被vue组件覆盖,所以每次要新建一个挂载点内容,设置id="toImg"
// 新建挂载点内容
const node = document.getElementById('hideNode')
node.innerHTML = '<div id="toImg"></div>'
4、利用vue动态构建组件,并挂载到id="toImg"
上
ApplyCard().then(res => {
// 获取vue组件
const temp = res.default
const Card = Vue.extend(temp)
// 动态挂载相应的组件
// 获取组件,这里采用的是模板编译
// -- 存在问题:上面更换了vue,导致在组件没有显示的页面,渲染组件会报错: element组件以及自定义全局组件没有引入
// const vueComponent = new Card({
// el: '#toImg',
// propsData: {
// info: {}
// }
// })
// 动态挂载相应的组件改成render函数渲染
const vueComponent = new Vue({
el: '#toImg',
render: function (h) {
return <Card info={info}></Card>
}
})
// 等加载完之后,获取dom
vueComponent.$nextTick(() => {
const node = vueComponent.$el
// 生成图片并分享招乎
dom2img(node).then(img => {
// 处理base64格式的img
})
})
})
更多推荐
所有评论(0)