最近接到一个需求,需要在小程序中实现页面截图,我一开始的考虑是使用官方提供的扩展组件wxml-to-canvas,但是实际体验下来效果很糟糕,首先它并不能截取实际的页面,而是必须传入wxml
和wxss
;然后他能支持的效果也很少,并不能满足需求中稍微复杂的效果。最终我决定用web-view加载的网页中使用html2canvas来实现功能。
实际代码
网页部分我用了vue
,首先需要安装html2canvas
npm install html2canvas
页面中引入
import html2canvas from 'html2canvas';
需要截图的dom节点上添加ref属性
<div ref="page">
截图代码
...
document.body.scrollTop = 0;
// 将页面滚动至顶部后再开始截图,才能保证截图的完整
html2canvas(this.$refs.page, {
allowTaint: false,
useCORS: true,
width: document.body.scrollWidth,
height: document.body.scrollHeight
// 实际体验中发现最好设置宽高为页面的宽高才能获得完整的截图
}).then(canvas => {
this.savedPic = canvas.toDataURL('images/png')
// 用于在页面中展示的截图完成的网址
...
// 以下代码为模拟a标签的点击直接下载截图
// 但是这部分代码在移动端网页和小程序中并不会生效
let a = document.createElement('a'),
blob = this.dataURLToBlob(canvas.toDataURL('images/png'));
a.setAttribute('href', URL.createObjectURL(blob));
a.setAttribute('download', 'pic.png');
document.body.appendChild(a);
a.click();
URL.revokeObjectURL(blob);
document.body.removeChild(a);
});
...
兼容性
网页毕竟不是原生小程序,还是会存在一些兼容性问题,比如网页中不能使用小程序的wx.saveImageToPhotosAlbum直接保存生成好的截图。移动端和微信中也不支持模拟a标签的点击来下载图片,最终只能通过展示生成的截图并提示用户长按图片来实现保存图片的功能,用户体验会差点,但是考虑到截图效果比wxml-to-canvas
好太多了,还是可以接受的。
最后说一下html2canvas
的支持度,目前实际用下来发现不支持的样式为__阴影__和__伪元素__,其他基本上都支持。网页中的图片必须为本地图片或者支持跨域的网络图片。用到图片的地方建议直接使用img
标签,而不是背景图片,img
标签展示的图片清晰度远远高于背景图片。