项目背景:企微应用推送的表格数据需要一键生成图片,且有可以分享到微信、企业微信和保存到本地的功能。
tips:企微内部只要生成图片了,就可以拉起分享和保存,所以只考虑生成图片
1、html2canvas
安卓端可以生成,iOS生成不了,直接一个蓝色问号的icon,继续尝试第二种方案。
2、dom-to-image
安卓端可以正常生成,iOS这回可算出来东西了,不过样式让人捉急,都挤在一块了。查阅说flex布局都不行,于是改成grid,看起来没问题了,but...表格直接空白了。再次焦灼查阅资料,总结下来大概是由于我们要生成图片的页面是用的antd table组件,数据有点多,有滑动条,不行。所以这个库再次被be。
3、dom-to-image-more
就在我一筹莫展之际,chat告诉我还有dom-to-image-more这玩意儿,是dom-to-image的优化版本,很好的解决了iOS的兼容性问题...很好,说干就干,而且看到这位大佬的文章,还有高级用法,可以指定图片尺寸、添加水印等,这不就是我梦寐以求的库库吗?于是呼哧呼哧用起来,结果还是跟方案二一样be了。fine
4、html-to-image
最终,不这还没到最终,我引入这个库以后,生成图片之前先将表格宽度加到最大,不让table内部存在滚动条,而是直接利用整个视窗的滚动条。然后我梦寐以求的iOS生成图片终于实现了。但是,不能缩放,这算什么事儿,生成图片以后图片是不完整的,虽然分享出去是完整且高清的一张图。
最后的方案是:创建一个新的Canvas对象,设置它的宽高与图片的宽高相同,然后将图片绘制在画布上,并将画布转换为base64格式的URL。最后,将该URL赋值给指定的DOM节点(LongChat)的src属性,终于实现了完整且可以缩放在屏幕正中间的一个图例。代码如下:
import { toSvg } from 'html-to-image'
//点击生成图片
const createScreen = () => {
$('.create').hide() // 隐藏生成图标
Toast.loading('正在生成图片:)', 3)
drawImg().then(() => {
Toast.info('生成图片成功!', 2)
})
}
}
function drawImg () {
return new Promise((resolve, reject) => {
setTimeout(() => {
try {
toSvg(mainRef.current, {
allowTaint: true,
useCORS: true //支持跨域
})
.then(function (dataUrl) {
var img = new window.Image()
img.onload = function () {
var canvas = document.createElement('canvas')
canvas.width = img.width
canvas.height = img.height
var context = canvas.getContext('2d')
context.drawImage(img, 0, 0)
var dataURL = canvas.toDataURL('image/png', 0.5)
$('#LongChat').attr('src', dataURL)
$('#mask').show() //展示蒙层
resolve()
}
img.src = dataUrl
})
.catch(function (error) {
reject(error)
})
} catch (err) {
reject(err)
}
}, 500)
})
}