使用html2canvas实现网页截图


手头一个项目需求需要在用户一系列动作完成后提供“保存图片”的功能,类似于网页截图,实际实现中踩了多次坑,mark一下

html2canvas

经过调研之后,发现html2canvas这个库算是一个比较成熟的工具,但其latest version和0.5.0-beta3之前的版本存在截图不全、ios兼容性问题,最终使用版本为:html2canvas 0.5.0-beta3

使用

使用很简单,可以直接通过script标签在html直接引入, 然后在事件中code:

html2canvas(document.querySelector(selector));

会返回一个promise,然后通过.then()或者async await拿到返回的对象res是一个截图后的canvas标签,将这个标签res.toDataURL('image/jpeg', 0.2) 拿到截图的base64数据,赋值给一个imgsrc即可,但是实际上我们的需求是可以实现一键保存图片,即用户点击一个button就可以download一张图片,经测,安卓端可以完美保存,但是ios不可以(猜测是ios的安全机制?)既然这样就折中引导用户“长按保存”,那么我们的code就根据设备的不同进行不同的操作,具体的code:

handleType = () => {
    let UA = window.navigator.userAgent,
        isHupuApp = /kanqiu/gi.test(UA),
        isAndroid = /android|adr|linux/gi.test(UA),
        isIOS = /iphone|ipod|ipad/gi.test(UA) && !isAndroid;
   
    this.setState({
      isIOS
    })

  }

handleSavePic = () => {
    console.log('ios',this.state.isIOS);
    if(this.state.isIOS){
      // iPhone 每一步进行打印,方便定位问题(生产删除)
      console.log('ios保存图片start');
      this.drawCanvas('.main-warp').then((res)=>{
        console.log('拿到截图canvas', res)
        let base64 = res.toDataURL('image/jpeg', 0.2);
        this.setState({
          show: true
        },()=>{
          // this.refs.savePic是我们的占位图,用于展示
          this.refs.savePic.src = base64;
          console.log('ios保存图片end');
        })
      })
    }else{
      // 安卓
      Toast.loading('保存中...', 0, () => {});
      this.drawCanvas('.main-warp').then((res)=>{
        console.log('拿到canvas对象')
        let base64 = res.toDataURL('image/jpeg', 0.2);
        console.log('canvas转为base64了,准备上传');
        let downloadAPI = 'http://****.hupu.com/down/';
        axios.post('http://****.hupu.com/upload',{
          images: base64
        }).then((res)=>{
          downloadAPI = downloadAPI + res.data.pic_url;
          console.log('下载地址',downloadAPI);
          // 利用a标签的点击机制实现一键下载
          let a = document.createElement("a");
          a.href = downloadAPI;
          a.click();
          Toast.hide()
        })
      }).catch((err)=>{
        console.log(err);
        Toast.info('保存失败,请稍后再试',1);
      })
    }
  }

安卓端实现一键下载

安卓端我们实现一键下载的时候需要后端进行配合,提供一个上传/下载接口,上传时将img的base64数据传递给后端,后端返回一个download img地址,然后我们通过访问这个img地址,进行下载保存到用户手机中。自动下载的实现是通过后端设置响应后实现的,我们可以在network查看:
1563348910996.jpg


html2canvas的问题

在使用中发现了html2canvas会出现截图不全(网络img无法截到):
如何解决

  • 网络图片加载改用base64

文字截图不全(只出现部分)
如何解决

  • 这个问题的定位是最关键的,前期出现问题是没有办法直接定位到的,只能进行多种尝试
  • 最后发现:改变文字标签(p textarea input)等标签的位置,如果在当前位置无法截完整,且使用了div包裹了文字标签,就跳出当前父标签,不用包裹;如果仍不行就再改变节点位置,当然样式的问题我们可以有多种方法实现,最后发现能够成功截完整文字(应该是html2canvas框架的问题)

html2canvas如何实现的截图?

html2canvas加载后将会浏览页面上的所有元素,遍历集合所有页面元素的信息,通过从DOM读取的足够信息去建立一个页面的展示镜像。所以如果一些标签和css书写的有问题,就会出现无法渲染的情况。
当html2canvas工作的时候,html中会出现一个隐藏标签,html2canvas就是通过它去遍历元素获取信息渲染canvas的,最后渲染完毕后该标签消失

声明:GodGc's World|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - 使用html2canvas实现网页截图


軟件工程沒有銀彈