Skip to content

前言

相信有很多的小伙伴在开发过程中进行绘制图片,或者截图等,今天我把使用的做一个总结分享给大家,避免入坑。

安装html2canvas

js
npm i -D html2canvas
npm i -D html2canvas

引入html2canvas

在所需要使用的组件上引入html2canvas

js
import html2canvas from "html2canvas";
import html2canvas from "html2canvas";

添加ref获取元素

html部分:

js
<div class="m-html2canvas">
  <div ref="canvasRef" class="m-canvasRef">
    <div class="m-imageList" v-for="item in imageList" :key="item.id">
      <img :src="item.path" alt="" />
    </div>
  </div>
  <div class="m-showImage" v-if="imgUrl">
    <img :src="imgUrl" alt="" />
  </div>
  <div class="m-btn">
    <el-button type="primary" @click="createImageQrcode">合成图片</el-button>
  </div>
</div>
<div class="m-html2canvas">
  <div ref="canvasRef" class="m-canvasRef">
    <div class="m-imageList" v-for="item in imageList" :key="item.id">
      <img :src="item.path" alt="" />
    </div>
  </div>
  <div class="m-showImage" v-if="imgUrl">
    <img :src="imgUrl" alt="" />
  </div>
  <div class="m-btn">
    <el-button type="primary" @click="createImageQrcode">合成图片</el-button>
  </div>
</div>

data部分:

js
imageList: [
  {
    path: "https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF",
    id: 1
  },
  {
    path: "https://img2.baidu.com/it/u=3231735899,2029570314&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500",
    id: 2
  },
  {
    path: "https://t7.baidu.com/it/u=1956604245,3662848045&fm=193&f=GIF",
    id: 3
  }
],
imgUrl: ""
imageList: [
  {
    path: "https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF",
    id: 1
  },
  {
    path: "https://img2.baidu.com/it/u=3231735899,2029570314&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500",
    id: 2
  },
  {
    path: "https://t7.baidu.com/it/u=1956604245,3662848045&fm=193&f=GIF",
    id: 3
  }
],
imgUrl: ""

methods部分:

具体的html2canvas配置项可以看官网

js
methods: {
    createImage() {
      this.$nextTick(() => {
        const canvas = document.createElement("canvas");
        // 获取要生成图片的 DOM 元素
        let canvasDom = this.$refs.canvasRef;
        // 获取指定的宽高
        const width = parseInt(window.getComputedStyle(canvasDom).width);
        const height = parseInt(window.getComputedStyle(canvasDom).height);
        // console.log("获取指定的宽高", width, height)
        // 宽高扩大 2 倍 处理图片模糊
        canvas.width = width;
        canvas.height = height;
        canvas.style.width = width / 2 + "px";
        canvas.style.height = height / 2 + "px";

        const context = canvas.getContext("2d");
        context.scale(1, 1);
        // context.fillStyle = '#FFFFFF'
        context.fillRect(0, 0, canvas.width, canvas.height);
        const options = {
          backgroundColor: null,
          canvas: canvas,
          useCORS: true,//配置允许跨域
          // scale:1,
          // windowWidth: document.body.scrollWidth,
          // windowHeight: document.body.scrollHeight,
          // x: 0,
          // y: window.pageYOffset,
          // allowTaint: true,
          // background: "#ffffff", // 一定要添加背景颜色,否则出来的图片,背景全部都是透明的
          dpi: 300 // 处理模糊问题
        };
        console.log("获取指定的宽高", width, height, canvas);
        html2canvas(canvasDom, options)
          .then(canvas => {
            try {
              // 生成图片地址
              this.imgUrl = canvas.toDataURL("image/png");
              console.log("canvas.toDataURL('image/png')", this.imgUrl);
            } catch (e) {
              alert("图片跨域,保存失败");
            }
          })
          .catch(err => {
            console.log("绘制失败");
          });
      });
    }
  }
methods: {
    createImage() {
      this.$nextTick(() => {
        const canvas = document.createElement("canvas");
        // 获取要生成图片的 DOM 元素
        let canvasDom = this.$refs.canvasRef;
        // 获取指定的宽高
        const width = parseInt(window.getComputedStyle(canvasDom).width);
        const height = parseInt(window.getComputedStyle(canvasDom).height);
        // console.log("获取指定的宽高", width, height)
        // 宽高扩大 2 倍 处理图片模糊
        canvas.width = width;
        canvas.height = height;
        canvas.style.width = width / 2 + "px";
        canvas.style.height = height / 2 + "px";

        const context = canvas.getContext("2d");
        context.scale(1, 1);
        // context.fillStyle = '#FFFFFF'
        context.fillRect(0, 0, canvas.width, canvas.height);
        const options = {
          backgroundColor: null,
          canvas: canvas,
          useCORS: true,//配置允许跨域
          // scale:1,
          // windowWidth: document.body.scrollWidth,
          // windowHeight: document.body.scrollHeight,
          // x: 0,
          // y: window.pageYOffset,
          // allowTaint: true,
          // background: "#ffffff", // 一定要添加背景颜色,否则出来的图片,背景全部都是透明的
          dpi: 300 // 处理模糊问题
        };
        console.log("获取指定的宽高", width, height, canvas);
        html2canvas(canvasDom, options)
          .then(canvas => {
            try {
              // 生成图片地址
              this.imgUrl = canvas.toDataURL("image/png");
              console.log("canvas.toDataURL('image/png')", this.imgUrl);
            } catch (e) {
              alert("图片跨域,保存失败");
            }
          })
          .catch(err => {
            console.log("绘制失败");
          });
      });
    }
  }

style部分:

js
.m-html2canvas {
  display: flex;
}
.m-canvasRef {
  width: 500px;
  height: 500px;
  /* border: 1px solid red; */
  /* box-sizing: border-box; */
  box-shadow: 10px 10px 5px #888888;
}

.m-imageList {
  width: 500px;
  height: calc(500px / 3);
}

img {
  width: 100%;
  height: 100%;
  float: left;
}

.m-showImage {
  margin-left: 50px;
  background: red;
  width: 500px;
  height: 500px;
}

.m-btn {
  margin-left: 50px;
}
.m-html2canvas {
  display: flex;
}
.m-canvasRef {
  width: 500px;
  height: 500px;
  /* border: 1px solid red; */
  /* box-sizing: border-box; */
  box-shadow: 10px 10px 5px #888888;
}

.m-imageList {
  width: 500px;
  height: calc(500px / 3);
}

img {
  width: 100%;
  height: 100%;
  float: left;
}

.m-showImage {
  margin-left: 50px;
  background: red;
  width: 500px;
  height: 500px;
}

.m-btn {
  margin-left: 50px;
}

以上就是简单的一种html2canvas的截图使用了。这里会有一个问题存在,因为生成的图片是base64的,将base64地址复制打开的时候图片的底部会失去一部分成了白色,但是在页面中直接显示的话是正常的,至今没能找到原因。

跨域问题

在配置了useCORS = true后还是会出现跨域问题,譬如这样:

1136101-20200211121500189-1366055111.png

有两种解决方式:

第一种:后端需要在服务器IIS上的HTTP响应标头设置,最简单粗暴的方法就是全部设置成*,不过这样安全性也低,自己可以根据自己需求设置:

js
access-control-allow-credentials:true
Access-Control-Allow-Headers:*
access-control-allow-origin:*
access-control-allow-credentials:true
Access-Control-Allow-Headers:*
access-control-allow-origin:*

第二种:在img标签上设置 crossorigin="anonymous" 属性,但是这样还是不行的,还是会报跨域问题,最后在src图片地址后面加上时间戳,有人说要加固定的参数,不然没有缓存,会一直请求,因为我们的页面渲染的时候,有协商缓存和强缓存的说法,大部分用来减少当页面刷新时,防止页面多次跟服务器请求,当我们国内访问github是一样的道理。但是我用的时候发现加上固定参数还是会报跨域问题。

js
......
    <img
      :src="staffQrCodeDialogBg1 + '?' + new Date().getTime()"
      alt=""
      crossOrigin="anonymous"
    />
......
......
    <img
      :src="staffQrCodeDialogBg1 + '?' + new Date().getTime()"
      alt=""
      crossOrigin="anonymous"
    />
......

我一般都是使用第二种,前端自行解决,速度快,效率高

总结

html2canvas填坑之旅就这样完成了,一共有三个问题,图片模糊问题、跨域问题、图片底部留白问题

今年打算逼自己去总结和学习,规划一定的时间来写文章来分享自己的所遇所学,来帮助大家避免入坑。