一、前言
最近项目里要求要把当前地图截图展示在小窗里,之前没接触这种请求,于是我就百度了一下,发现有这么一块插件html2Canvas,它能够将dom元素转换成canvas进行截图保存,而且兼容性比较好,基本Firefox 3.5+, Google Chrome, Opera新的版本, IE9以上的浏览器都支持,就决定试用一下html2Canvas插件,看下能否实现这样子的要求。
二、过程
1、首先我们需要在vue项目(2.0项目)里下载并引入一下
// 下载
npm install html2canvas
// 引入
import html2canvas from 'html2canvas'
复制代码
2、接下来就是调用了,用法也很简单
过程就是 1、获取该元素,打算截图的dom元素,用原生js获取,用ref获取都可以,没有限制
2、手动临时创建一个canvas,在这个基础上进行dom元素的canvas化
3、调用html2canvas(dom, options)方法
4、then之后,会返回一个canvas对象,我们这个调用canvas.toDataURL('image/png'),
把canvas转成base64。
语法小知识: canvas.toDataURL(type, encoderOptions)
type是图片格式,默认为 image/png,可以是其他image/jpeg等
encoderOptions,0到1之间的取值,主要用来选定图片的质量,默认值是0.92,超出范围也会选择默认值。
复制代码
5、这个base64可直接给img标签使用
6、如果需要下载保存,可以调用downloadImage函数进行下载保存
// 页面元素转图片
toImage() {
// 获取父标签,意思是这个标签内的 DOM 元素生成图片
// map是给截图范围内的父级元素自定义的ref名称
const canvasBox = this.$refs.map
// 手动创建一个 canvas 标签
const canvas = document.createElement('canvas')
if (canvasBox) {
// 获取父级的宽高
const width = parseInt(window.getComputedStyle(canvasBox).width)
const height = parseInt(window.getComputedStyle(canvasBox).height)
canvas.style.width = width + 'px'
canvas.style.height = height + 'px'
const context = canvas.getContext('2d')
const options = {
backgroundColor: null, // 设置背景色为透明
canvas: canvas,
useCORS: true, //是否尝试使用CORS从服务器加载图像,解决跨域问题
tainttest: true, // 是否在渲染前测试图片
logging: false // 不启动日志调试
}
// canvasBox是要截图的元素,options是一些相关配置
html2canvas(canvasBox, options).then((canvas) => {
// toDataURL 图片格式转成 base64
const dataURL = canvas.toDataURL('image/png')
// 下载图片到本地
this.downloadImage(dataURL)
})
}
},
// 下载图片
downloadImage(dataURL) {
// 新建一个a标签
var oA = document.createElement("a");
oA.download = '截图';// 设置下载的文件名
oA.href = dataURL;
document.body.appendChild(oA);
oA.click(); // 模拟点击a标签
oA.remove(); // 下载之后把创建的元素删除
}
复制代码
三、可能遇到的问题
1、截图后图片和原先效果不太符合
html2Canvas是经过计算转成canvas的,对于自定义的样式有可能不支持。
2、文字样式丢失且都变成为最小号字体。
解决方案: 需要截图的节点根样式添加font-variant: normal;
3、文字向下偏移。
解决方案: 指定html2canvas的版本号为1.0.0-alpha.12
4、不完整,缺失,留白。
出现情况: 当截图区域超过视图高度,且滚动条未处在顶部时,会出现。
解决方案1:截图之前控制滚动条至顶部。
解决方案2:设置options里的scrollX为0, scrollY为0。
如果还有偏移,检查一下绘制的box上是不是加了transform:translateX(-50%)
5、模糊,不清晰。
出现情况: 通常是图片设置为背景的情况下,截图会比较模糊。
解决方案: 将背景图通过img标签加定位的方式实现。
6、截图空白
出现情况: 截图的dom元素里有非本地的图片资源
解决方案: 给 img 元素设置 crossOrigin
属性,值为 anonymous
,同时要求图片服务端 设置允许跨域(返回 CORS 头),最后是options里设置useCORS为true,允许html2Canvas跨域 加载图片资源。尤其是地图,图片资源一定要服务端设置允许跨域,不然会截空白屏。
7、想要不截取某个子元素
解决方案: 调用options里的ignoreElements函数,匹配到对应节点,返回true就可以隐藏该元素
四、总结
插件好用是好用,但是坑也不少,希望我的文章能帮大家避避坑。
五、options的相关配置
详细的options配置表,我整理了一些,有需要可以自取:
名称 | 默认值 | 描述 | |
---|---|---|---|
allowTaint | false | 是否允许跨域图像污染画布(默认不允许渲染跨域图片) | |
backgroundColor | #ffffff | canvas画布背景色(如果未在DOM中指定)。设置null 为透明 |
|
canvas | null | 使用现有canvas 元素用作绘图的基础,即在该canvas基础上继续渲染我们的element |
|
foreignObjectRendering | false | 如果浏览器支持,是否使用ForeignObject渲染 | |
dpi | 96 | 可以提高清晰度,缩放比例scale = dpi/96 (该属性是新加的,低版本可能没有) | |
imageTimeout | 15000 | 加载图像的超时时间(以毫秒为单位)。设置0为禁用超时。 | |
ignoreElements | (element) => false | 谓词功能,可从渲染中删除匹配的元素。 | |
logging | true | 启用日志以进行调试 | |
onclone | null | 克隆文档以进行渲染时调用的回调函数可用于修改将要渲染的内容,而不会影响原始源文档。onclone回调函数返回复制的文档根节点document,onclone:(doc)=>{} | |
proxy | null | 用于加载跨域图像的代理的网址。如果保留为空,则不会加载跨域图像。 | |
removeContainer | true | 是否清除HTML2canvas临时创建的克隆DOM元素 | |
scale | window.devicePixelRatio | 用于渲染的缩放比。默认为浏览器设备像素比率。 | |
taintTest | false | 是否在渲染前测试图片 | |
timeout | 0 | Number类型,单位毫秒,设置图片加载延迟 | |
useCORS | false | 是否尝试使用CORS从服务器加载图像 | |
width | element width | canvas画布的宽度 | |
height | element width | canvas画布的高度 | |
x | element x-offset | 裁剪画布X坐标 | |
y | element y-offset | 裁剪画布y坐标 | |
scrollX | element scrollX | 渲染元素时要使用的x滚动位置(例如,如果Element使用position: fixed) | |
scrollY | element scrollY | 渲染元素时要使用的y滚动位置(例如,如果Element使用position: fixed) | |
windowWidth | window.innerWidth | 渲染Element时要使用的窗口宽度,这可能会影响媒体查询之类的内容 | |
windowHeight | window.innerHeight | 渲染Element时要使用的窗口高度,这可能会影响媒体查询之类的内容 |
ps:今天更新比较水了
作者:地霊殿__三無
链接:https://juejin.cn/post/7125449911750885413
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。