成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Canvas 進(jìn)階(二)寫一個(gè)生成帶logo的二維碼npm插件

Chaz / 635人閱讀

摘要:背景最近接觸到的需求,前端生成一個(gè)帶企業(yè)的二維碼,并支持點(diǎn)擊下載它。

背景

最近接觸到的需求,前端生成一個(gè)帶企業(yè)logo的二維碼,并支持點(diǎn)擊下載它。

實(shí)現(xiàn)

在前面的文章有講到如何用 canvas 畫二維碼,在此基礎(chǔ)上再畫一個(gè)公司logo,并提供下載的方法供調(diào)用,再封裝成 npm 插件

模塊名稱: qrcode-with-logos

github地址:https://github.com/zxpsuper/qrcode-with-logos

npm地址:https://www.npmjs.com/package/qrcode-with-logos

核心代碼

將整個(gè)封裝成一個(gè) QrCodeWithLogo類,并提供三個(gè)方法:

interface IQrCodeWithLogo {
  toCanvas(): Promise;
  toImage(): Promise;
  downloadImage(name: string): void;
}

class QrCodeWithLogo implements IQrCodeWithLogo {
  option: BaseOptions;
  constructor(option: BaseOptions) {
    this.option = option;
    return this;
  }
  toCanvas = () => {
    return toCanvas.call(this, this.option);
  };
  toImage = () => {
    return toImage.call(this, this.option);
  };
  downloadImage = (name: string) => {
    saveImage(this.option.image, name);
  };
}
1. toCanvas()

此方法用到了庫(kù)qrcodetoCanvas方法

export const toCanvas = (options: BaseOptions) => {
  return renderQrCode(options)
    .then(() => options)
    .then(drawLogo);
};

這里先用qrcode庫(kù)畫出二維碼的canvas

import QRCode = require("qrcode");

const toCanvas = promisify(QRCode.toCanvas);

export const renderQrCode = ({
  canvas,
  content,
  width = 0,
  nodeQrCodeOptions = {}
}: BaseOptions) => {
  // 容錯(cuò)率,默認(rèn)對(duì)內(nèi)容少的二維碼采用高容錯(cuò)率,內(nèi)容多的二維碼采用低容錯(cuò)率
  // according to the content length to choose different errorCorrectionLevel
  nodeQrCodeOptions.errorCorrectionLevel =
    nodeQrCodeOptions.errorCorrectionLevel || getErrorCorrectionLevel(content);

  return getOriginWidth(content, nodeQrCodeOptions).then((_width: number) => {
    // 得到原始比例后還原至設(shè)定值,再放大4倍以獲取高清圖
    // Restore to the set value according to the original ratio, and then zoom in 4 times to get the HD image.
    nodeQrCodeOptions.scale = width === 0 ? undefined : (width / _width) * 4;
    // @ts-ignore
    return toCanvas(canvas, content, nodeQrCodeOptions);
  });
};

promisify()是封裝的一個(gè)方法,用于減少return promise時(shí)的代碼,方便書寫

export const promisify = (f: Function): Function => {
  return function() {
    const args = Array.prototype.slice.call(arguments);
    return new Promise(function(resolve, reject) {
      args.push(function(err: object, result: object) {
        if (err) reject(err);
        else resolve(result);
      });
      f.apply(null, args);
    });
  };
};

畫出canvas,緊接著判斷是否有l(wèi)ogo, 如果有就畫logo,這里有兩種模式:

一種是直接畫圖 ctx.drawImage(image, logoXY, logoXY, logoWidth, logoWidth);,可拓展性不強(qiáng)。

一種是canvas疊加,使用 ctx.createPattern(canvasImage, "no-repeat"); 可以實(shí)現(xiàn)更多復(fù)雜的效果

export const drawLogo = ({ canvas, content, logo }: BaseOptions) => {
  if (!logo) {
    return;
  }
  // @ts-ignore
  const canvasWidth = canvas.width;
  const {
    logoSize = 0.15,
    borderColor = "#ffffff",
    bgColor = borderColor || "#ffffff",
    borderSize = 0.05,
    crossOrigin,
    borderRadius = 8,
    logoRadius = 0
  } = logo;
  let logoSrc = typeof logo === "string" ? logo : logo.src;
  let logoWidth = canvasWidth * logoSize;
  let logoXY = (canvasWidth * (1 - logoSize)) / 2;
  let logoBgWidth = canvasWidth * (logoSize + borderSize);
  let logoBgXY = (canvasWidth * (1 - logoSize - borderSize)) / 2;
  // @ts-ignore
  const ctx = canvas.getContext("2d");

  // logo 底色, draw logo background color
  canvasRoundRect(ctx)(
    logoBgXY,
    logoBgXY,
    logoBgWidth,
    logoBgWidth,
    borderRadius
  );
  ctx.fillStyle = bgColor;
  ctx.fill();

  // logo
  const image = new Image();
  if (crossOrigin || logoRadius) {
    image.setAttribute("crossOrigin", crossOrigin || "anonymous");
  }
  image.src = logoSrc;

  // 使用image繪制可以避免某些跨域情況
  // Use image drawing to avoid some cross-domain situations
  const drawLogoWithImage = (image: any) => {
    ctx.drawImage(image, logoXY, logoXY, logoWidth, logoWidth);
  };

  // 使用canvas繪制以獲得更多的功能
  // Use canvas to draw more features, such as borderRadius
  const drawLogoWithCanvas = (image: any) => {
    const canvasImage = document.createElement("canvas");
    canvasImage.width = logoXY + logoWidth;
    canvasImage.height = logoXY + logoWidth;
    canvasImage
      .getContext("2d")
      .drawImage(image, logoXY, logoXY, logoWidth, logoWidth);

    canvasRoundRect(ctx)(logoXY, logoXY, logoWidth, logoWidth, logoRadius);
    ctx.fillStyle = ctx.createPattern(canvasImage, "no-repeat");
    ctx.fill();
  };

  // 將 logo繪制到 canvas上
  // Draw the logo on the canvas
  return new Promise((resolve, reject) => {
    image.onload = () => {
      logoRadius ? drawLogoWithCanvas(image) : drawLogoWithImage(image);
      resolve();
    };
  });
};
2. toImage()

此方法利用之前的toCanvas()方法,生成canvas后拿到 canvas.toDataURL() 的值,賦給

npm 模塊導(dǎo)入:

import QrCodeWithLogo from "qrcode-with-logos";
let qrcode = new QrCodeWithLogo({
  canvas: document.getElementById("canvas"),
  content: "https://github.com/zxpsuper",
  width: 380,
  //   download: true,
  image: document.getElementById("image"),
  logo: {
    src: "https://avatars1.githubusercontent.com/u/28730619?s=460&v=4"
  }
});

qrcode.toCanvas().then(() => {
  qrcode.toImage().then(() => {
    setTimeout(() => {
      qrcode.downloadImage("hello world");
    }, 2000);
  });
});

當(dāng)然你也可以

That is all.

更多推薦

前端進(jìn)階小書(advanced_front_end)

前端每日一題(daily-question)

webpack4 搭建 Vue 應(yīng)用(createVue)

Canvas 進(jìn)階(一)二維碼的生成與掃碼識(shí)別

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/105208.html

相關(guān)文章

  • Canvas 進(jìn)階(三)ts + canvas”辨色“小游戲

    摘要:話不多說(shuō),先上和項(xiàng)目源碼有趣的是,在我寫完這篇文章之后,發(fā)現(xiàn)愛(ài)編程的李先森也寫了一篇手寫辨色力小游戲?qū)崿F(xiàn)方式有所不同,可以對(duì)比下。 1. 背景 之前寫過(guò)一篇文章 ES6 手寫一個(gè)辨色小游戲, 感覺(jué)好玩挺不錯(cuò)。豈料評(píng)論區(qū)大神頻出,其中有人指出,打開(kāi)控制臺(tái),輸入以下代碼: setInterval( ()=>document.querySelector(#special-block).cli...

    Aceyclee 評(píng)論0 收藏0
  • canvas繪制海報(bào)+維碼,滿足絕大部分場(chǎng)景

    摘要:無(wú)需任何第三方依賴,輕型工具庫(kù)。繪制海報(bào),生成帶的二維碼。默認(rèn)重新編輯最終圖片壓縮比,默認(rèn)基礎(chǔ)類型參數(shù)表示一個(gè)圖片部分。之間表示一個(gè)二維碼部分參數(shù)類型描述指定為二維碼類型要繪制的內(nèi)容。通過(guò)控制邊框顏色,默認(rèn)為默認(rèn)為容錯(cuò)等級(jí)。 canvas_x 無(wú)需任何第三方依賴,輕型工具庫(kù)。canvas繪制海報(bào),生成帶logo的二維碼。也可生成編輯界面,用戶自定義輸入,一鍵生成等等 默認(rèn)開(kāi)啟圖片跨域,...

    bluesky 評(píng)論0 收藏0
  • 個(gè)人分享--web前端學(xué)習(xí)資源分享

    摘要:前言月份開(kāi)始出沒(méi)社區(qū),現(xiàn)在差不多月了,按照工作的說(shuō)法,就是差不多過(guò)了三個(gè)月的試用期,準(zhǔn)備轉(zhuǎn)正了一般來(lái)說(shuō),差不多到了轉(zhuǎn)正的時(shí)候,會(huì)進(jìn)行總結(jié)或者分享會(huì)議那么今天我就把看過(guò)的一些學(xué)習(xí)資源主要是博客,博文推薦分享給大家。 1.前言 6月份開(kāi)始出沒(méi)社區(qū),現(xiàn)在差不多9月了,按照工作的說(shuō)法,就是差不多過(guò)了三個(gè)月的試用期,準(zhǔn)備轉(zhuǎn)正了!一般來(lái)說(shuō),差不多到了轉(zhuǎn)正的時(shí)候,會(huì)進(jìn)行總結(jié)或者分享會(huì)議!那么今天我就...

    sherlock221 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<