博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一、前言

最近项目里要求要把当前地图截图展示在小窗里,之前没接触这种请求,于是我就百度了一下,发现有这么一块插件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就可以隐藏该元素

image.png

四、总结

插件好用是好用,但是坑也不少,希望我的文章能帮大家避避坑。

五、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:今天更新比较水了

image.png


作者:地霊殿__三無
链接:https://juejin.cn/post/7125449911750885413
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Live2D