前端生成图片,利用 html2canvas 生成

此项目以vue为例,引用方式是

cnpm install html2canvas -s
// 在用到的地方引用
import html2canvas from 'html2canvas'

不是 vue 的可以直接引用 js 文件,不多说话,直接上代码(注释都在里面了)

 printSeat() {
    this.$store.commit("updatePageLoading", ++this.$store.state.pageLoading)
    // 下面是这边需求,需要对打印出来的东西做一些样式调整,写的代码,可根据自己业务需求进行修改
    document.querySelectorAll('#chartList')[0].style.top = 0;
    document.querySelectorAll('#chartList')[0].style.left = 0;

    try {
      document.querySelectorAll('.group-area-right')[0].style.right = '180px';
    } catch (error) {

    }
    try {
      document.querySelectorAll('.group-area-left')[0].style.left = '180px';
    } catch (error) {

    }
    try {
      document.querySelectorAll('.area-class')[0].style.left = '180px';
    } catch (error) {

    }
    
    // 这边就是我们的业务代码了,也可以不用 document.createElement("canvas"), 直接进行html2canvas 进行生成图片,我这边因为图片过大,生成出来的图片很模糊,就进行了处理
    let canvas2 = document.createElement("canvas");
    let _canvas = document.querySelectorAll('#seatPrint')[0];

    let w = parseInt(window.getComputedStyle(_canvas).width);
    let h = parseInt(window.getComputedStyle(_canvas).height);

    //将canvas画布放大若干倍,然后盛放在较小的容器内,就显得不模糊了
    canvas2.width = w * 1.9;
    canvas2.height = h * 1.6;
    //可以按照自己的需求,对context的参数修改,translate指的是偏移量
    let context = canvas2.getContext("2d");
    context.scale(2, 2);
    // context.translate(100, 0);
    document.querySelectorAll('#seatPrint')[0].style.transform = 'scale(.8)';
    document.querySelectorAll('#seatPrint')[0].style.marginLeft = '-10%';
    document.querySelectorAll('#seatPrint')[0].style.width = '120%';

    let that = this
    // { canvas: canvas2 } 不处理的话是不用穿的,直接传第一个参数就行(需要生成的dom区域)
    html2canvas(document.querySelectorAll('#seatPrint')[0], { canvas: canvas2 }).then((canvas) => {
        // canvas.toDataURL() 输出的 base64
        const blob = this.convertBase64UrlToBlob(canvas.toDataURL()); // 转成bolb
        // 下载的文件名称
        const fileName = this.$route.query.planName + '座次图'
        if (window.navigator.msSaveOrOpenBlob) {
          navigator.msSaveBlob(blob, fileName);
        } else {
          // 创建 a 标签,开始下载
          const link = document.createElement('a');
          link.href = window.URL.createObjectURL(blob);
          link.download = fileName;
          //此写法兼容可火狐浏览器
          document.body.appendChild(link);
          const evt = document.createEvent("MouseEvents");
          evt.initEvent("click", false, false);
          link.dispatchEvent(evt);
          document.body.removeChild(link);
          // 样式恢复
          setTimeout(() => {
            this.$store.commit("updatePageLoading", --this.$store.state.pageLoading) 
            // 下面注释的代码,火狐浏览器不支持(苦恼,奈何客户用的是火狐,继续采坑)
            // document.querySelectorAll('.list-box')[0].style.zoom = 1; 
            document.querySelectorAll('#seatPrint')[0].style.transform = 'scale(1)';
            document.querySelectorAll('#seatPrint')[0].style.marginLeft = 0;
            document.querySelectorAll('#seatPrint')[0].style.width = '100%';
            try {
              document.querySelectorAll('.group-area-right')[0].style.right = '30px';
            } catch (error) {

            }
            try {
              document.querySelectorAll('.group-area-left')[0].style.left = '30px';
            } catch (error) {

            }
            try {
              document.querySelectorAll('.area-class')[0].style.left = '0px';
            } catch (error) {

            }
          }, 100)
        }
    }).catch(err => {
      this.$store.commit("updatePageLoading", --this.$store.state.pageLoading)  
    });
 convertBase64UrlToBlob(base64) {
      let parts = base64.split(";base64,");
      let contentType = parts[0].split(":")[1];
      let raw = window.atob(parts[1]);
      let rawLength = raw.length;
      let uInt8Array = new Uint8Array(rawLength);
      for (let i = 0; i < rawLength; i++) {
          uInt8Array[i] = raw.charCodeAt(i);
      }
      return new Blob([uInt8Array], { type: contentType });
  }

在中间遇到了一个奇怪的问题,就是chrome浏览器生成图片大约要3秒钟左右,而火狐浏览器能加载一分钟,提示显示

image

刚开始以为打印的dom元素比较多,然后就尝试了打印部分dom,都没有问题,只要已使用外层的dom就会提示,后来我改了dom元素的层级结构,然后就快了很多,中间尝试过直接后端生成,但是我觉得前端应该也没问题,网上查了说chrome 和 火狐浏览器都挺好用的,然后就开始改层级了

你可能感兴趣的:(前端生成图片,利用 html2canvas 生成)