Created
June 26, 2021 12:40
-
-
Save tesh254/9c4e424bad1a36438bb07f2c1da7c33c to your computer and use it in GitHub Desktop.
Generate a custom QR code with the help of node canvas, enabling headless QR generation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import QRCode from "qrcode"; | |
import { createCanvas, loadImage, CanvasRenderingContext2D, Image } from "canvas"; | |
import { IQrOptions } from "../interfaces"; | |
import SpacesService from "./spaces.service"; | |
export default class QRGeneratorService { | |
private qrOptions: IQrOptions; | |
private text: string; | |
constructor(text: string, options: IQrOptions) { | |
this.qrOptions = options; | |
this.text = text; | |
} | |
public async generateQRCode() { | |
try { | |
const initQR = await this.qrGenerator(); | |
const UPLOAD_DATA = new SpacesService().uploadToBucket(initQR, "image/png", "jpg", true) | |
return UPLOAD_DATA; | |
} catch (error) { | |
console.log(error) | |
throw { | |
...error | |
} | |
} | |
} | |
public async qrGenerator() { | |
const canvas = createCanvas(150, 150); | |
const ctx = canvas.getContext("2d"); | |
const WIDTH = this.qrOptions.size || 720 | |
await QRCode.toCanvas(canvas, this.text, { | |
margin: 1, | |
color: { | |
dark: this.qrOptions.color || "#000000", | |
light: this.qrOptions.background || "#ffffff" | |
}, | |
width: WIDTH | |
}) | |
if (this.qrOptions.logo) { | |
// ctx.save() | |
const LOGO_SIZE = this.qrOptions.logo_size || 120; | |
const image = await loadImage(this.qrOptions.logo); | |
const IMAGE_POSITION = (WIDTH / 2) - (LOGO_SIZE / 2); | |
let x = IMAGE_POSITION; | |
let y = IMAGE_POSITION; | |
let radius = 12; | |
ctx.beginPath(); | |
ctx.moveTo(x + radius, y); | |
ctx.lineTo(x + LOGO_SIZE - radius, y); | |
ctx.quadraticCurveTo(x + LOGO_SIZE, y, x + LOGO_SIZE, y + radius); | |
ctx.lineTo(x + LOGO_SIZE, y + LOGO_SIZE - radius); | |
ctx.quadraticCurveTo(x + LOGO_SIZE, y + LOGO_SIZE, x + LOGO_SIZE - radius, y + LOGO_SIZE); | |
ctx.lineTo(x + radius, y + LOGO_SIZE); | |
ctx.quadraticCurveTo(x, y + LOGO_SIZE, x, y + LOGO_SIZE - radius); | |
ctx.lineTo(x, y + radius); | |
ctx.quadraticCurveTo(x, y, x + radius, y); | |
ctx.closePath(); | |
ctx.clip() | |
ctx.drawImage(image, IMAGE_POSITION, IMAGE_POSITION, LOGO_SIZE, LOGO_SIZE) | |
} | |
return canvas.toBuffer("image/png") | |
} | |
private roundRect(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number, radius: number) { | |
ctx.beginPath(); | |
ctx.moveTo(x + radius, y); | |
ctx.lineTo(x + width - radius, y); | |
ctx.quadraticCurveTo(x + width, y, x + width, y + radius); | |
ctx.lineTo(x + width, y + height - radius); | |
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); | |
ctx.lineTo(x + radius, y + height); | |
ctx.quadraticCurveTo(x, y + height, x, y + height - radius); | |
ctx.lineTo(x, y + radius); | |
ctx.quadraticCurveTo(x, y, x + radius, y); | |
ctx.closePath(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment