canvas生成二維碼附帶icon並實現下載

canvas生成二維碼附帶icon並實現下載

https://blog.csdn.net/chy555chy/article/details/85785819

利用 qrcode 生成二維碼是不帶 icon 的,去網上查找解決方案需要修改源碼。
所以只好自己開搞了
效果如下:
帶有icon的二維碼
代碼如下

<template>
  <div>
    <!-- 二維碼和icon -->
    <img :src="rediusIconSrc" alt="ICON">
    <img :src="qrCodeSrc" alt="qrcode">
    <img :src="iconCodeSrc" alt="IconAndQrcode">
    <button @click="getQrcode">下載</button>
  </div>
</template>
<script>
import QRCode from 'qrcode'; // 需安裝 qrcode 插件;
export default {
  data() {
    return {
      qrCodeSrc: '',
      rediusIconSrc: '',
      iconCodeSrc: '',
      qrCodeW: '200',
      qrCodeH: '200',
      codeContext: 'text123',
      iconScale: 0.2 // icon 佔二維碼的比例;
    };
  },
  mounted() {
    this.getCanvas(this.codeContext);
  },
  methods: {
    getQrcode() {
      let _a = document.createElement('a');
      _a.href = this.iconCodeSrc;
      _a.download = '帶有 icon 的二維碼';
      _a.click();
    },
    getCanvas(codeContext, option = {errorCorrectionLevel: 'H', margin: 1}) {
        // 配置參數 參考https://github.com/soldair/node-qrcode#options
        // var opts = {
        //   errorCorrectionLevel: 'H', // 容錯級別 low, medium, quartile, high or L, M, Q, H.
        //   type: 'image/jpeg', // 圖片類型
        //   quality: 0.9, // 透明度 貌似沒啥效果
        //   maskPattern: 1, // 遮罩圖案
        //   margin: 1, // 二維碼距離邊框的距離 單位爲4px 默認值1個單位
        //   color: { // 二維碼 碼塊的顏色
        //     dark: '#010599FF', // 默認值 #000000
        //     light: '#FFBF60FF' // 默認值 #ffffff
        //   }
        // };

        QRCode.toDataURL(codeContext, option, (err, url) => {
          if (err) throw err;
          // 生成二維碼圖片地址
          this.qrCodeSrc = url;

          // 二維碼 轉化爲 canvas 並將 icon 畫入到 canvas 中,然後導出;
          this.addicon();
        });
    },
    // 生成帶邊框及圓角的 icon 圖片;
    addicon(X = 0, Y = 0, W, H, radius = 5, birderW = 2, borderColor = '#fff', isbgColor = true, bgColor = 'rgba(255,255,255, 1)') {
      let c = document.createElement('canvas');
        c.width = this.qrCodeW * this.iconScale;
        c.height = this.qrCodeH * this.iconScale;
        let _w = W || c.width, _h = H || c.height;
        let ctx = c.getContext('2d');

        // 是否設置背景顏色
        if (isbgColor) {
          ctx.fillStyle = bgColor;
          ctx.fillRect(0, 0, c.width, c.height);
        }
        this.drawRoundRect(ctx, X, Y, _w, _h, radius, birderW, borderColor);
        let img = document.createElement('img');

        // 網絡圖片直接給地址;
        img.src = 'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2069790559,642682254&fm=26&gp=0.jpg';

        // 如果是本地圖片請使用 require() 引入;
        // img.src = require(src); // src 不能使變量 會查找不到;

        // 解決 訪問網絡圖片屬於跨域操作 Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
        img.setAttribute('crossOrigin', 'Anonymous');
        img.onload = () => {
          ctx.clip();
          ctx.drawImage(img, 0, 0, 40, 40);
          ctx.restore();
          this.rediusIconSrc = c.toDataURL();
          this.mergeImg();
        };
    },
    // 圓角 icon 和 二維碼 合併到一起;
    mergeImg() {
      let c = document.createElement('canvas');
        c.width = this.qrCodeW;
        c.height = this.qrCodeH;
        let ctx = c.getContext('2d');
        let bg = document.createElement('img');
        let icon = document.createElement('img');
        bg.src = this.qrCodeSrc;
        icon.src = this.rediusIconSrc;

        let _bgLoad = new Promise((resolve, reject) => {
          try {
            bg.onload = () => resolve();
          } catch (error) {
            reject(error);
          }
        });
        let _iconLoad = new Promise((resolve, reject) => {
          try {
            icon.onload = () => resolve();
          } catch (error) {
            reject(error);
          }
        });

        Promise.all([_bgLoad, _iconLoad]).then(res => {
          let w = this.qrCodeW;
          let h = this.qrCodeH;
          let iconW = w * this.iconScale;
          let iconH = h * this.iconScale;
          let iconX = (w - iconW) / 2;
          let iconY = (h - iconH) / 2;
          // 畫二維碼
          ctx.drawImage(bg, 0, 0, w, h);
          // 畫icon
          ctx.drawImage(icon, iconX, iconY, iconW, iconH);
          // 轉化爲圖片 src;
          this.iconCodeSrc = c.toDataURL();
        }).catch(e => {
          console.log('error-', e);
        });
    },
    // 畫圓角 ctx 上下文 x,y 起始位置 width,height icon的寬高 radius 圓角的角度 lineWidth 邊框的寬度 lineColor 邊框的顏色
    drawRoundRect(ctx, x, y, width, height, radius, lineWidth, lineColor) {
      ctx.lineWidth = lineWidth;
      ctx.strokeStyle = lineColor;
      ctx.beginPath();
      ctx.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2);
      ctx.lineTo(width - radius + x, y);
      ctx.arc(width - radius + x, radius + y, radius, Math.PI * 3 / 2, Math.PI * 2);
      ctx.lineTo(width + x, height + y - radius);
      ctx.arc(width - radius + x, height - radius + y, radius, 0, Math.PI * 1 / 2);
      ctx.lineTo(radius + x, height + y);
      ctx.arc(radius + x, height - radius + y, radius, Math.PI * 1 / 2, Math.PI);
      ctx.closePath();
      ctx.stroke();
    }
  }
};
</script>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章