Open madmacc opened 2 years ago
I might check to do it on my local and make a pull request in the coming weeks months
Any news?
Not sure if this is helpful but I ended up using the canvas to generate a border myself and it works well.
import * as PImage from "pureimage"
import { Bitmap } from 'pureimage/types/bitmap';
import { saveAs } from 'file-saver';
async generateQrSticker(download: boolean) {
const element: any = document.querySelector('#qr-sticker');
const imgFrameWidth = 1500;
const imgFrameHeight = 1500;
const imgQrWidth = 1000 * (this.dynamicLink.qrParams ? this.dynamicLink.qrParams.qrSizePercent : 1);
const imgQrHeight = 1000 * (this.dynamicLink.qrParams ? this.dynamicLink.qrParams.qrSizePercent : 1);
const imgQrAdjust = 200;
const qrX = imgFrameWidth / 2 - (imgQrWidth / 2);
const qrY = imgFrameHeight / 2 - (imgQrHeight / 2);
console.log('imgQrWidth', imgQrWidth)
console.log('imgQrWidth', imgQrWidth)
const qrCodeFullSize = await this.getFullSizeQRCode();
const imgQrBlob = await qrCodeFullSize.getRawData('jpeg');
const imgQrB64 = await blobToBase64(imgQrBlob);
const borderThickness = 10;
const borderFromQrDistance = 50;
const fontSizeSmall = 50;
const fontSizeMedium = 80;
const fontSizeLarge = 120;
const adjTitleFontSize = fontSizeMedium * this.dynamicLink.qrParams.titleTextSizePercent;
const adSubTitleFontSize = fontSizeSmall * this.dynamicLink.qrParams.subTitleTextSizePercent;
const adjCtaFontSize = fontSizeLarge * this.dynamicLink.qrParams.ctaTextSizePercent;
let borderTextAdjust = 0;
// Colours
const qrForegroundColour = this.tenantPrivateData.qrCodeStyle.foregroundColor;
const qrCornerDotColor = this.tenantPrivateData.qrCodeStyle.cornerDotColor;
const qrBackgroundColour = this.tenantPrivateData.qrCodeStyle.backgroundColor;
const fgContrast = this.qrCodeService.getContrastScore(qrForegroundColour, '#ffffff');
const bgContrast = this.qrCodeService.getContrastScore(qrBackgroundColour, '#ffffff');
const primaryImgColour = fgContrast > bgContrast ? qrForegroundColour : qrBackgroundColour;
// Background image
const img1: Bitmap = PImage.make(imgFrameWidth, imgFrameHeight, null);
// get canvas context
const ctx = img1.getContext('2d');
// Background
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, imgFrameWidth, imgFrameHeight);
ctx.strokeStyle = primaryImgColour;
if (this.dynamicLink.qrParams.useBorder) {
console.log('drawing border')
ctx.lineWidth = borderThickness;
borderTextAdjust = (borderThickness + borderFromQrDistance) / 2;
// QR border
const x1 = (imgFrameWidth - imgQrWidth) / 2 - borderFromQrDistance;
const y1 = (imgFrameHeight - imgQrHeight) / 2 - borderFromQrDistance;
const w = imgQrWidth + (borderFromQrDistance * 2);
const h = imgQrHeight + (borderFromQrDistance * 2);
console.log('x1', x1)
console.log('y1', y1)
console.log('w', w)
console.log('h', h)
ctx.strokeRect(x1, y1, w, h);
} else {
// We need to adjust where the text is to center it if no border
borderTextAdjust = 0;
}
console.log('borderTextAdjust', borderTextAdjust)
// Text
const fontFamily = `'Poppins', sans-serif`;
ctx.font = `normal 600 ${adjTitleFontSize}px ${fontFamily}`;
ctx.fillStyle = primaryImgColour;
ctx.textAlign = "center";
if (this.dynamicLink.qrParams.subTitleText) {
ctx.fillText(`${this.dynamicLink.qrParams.titleText}`, imgFrameWidth / 2, 40 + adjTitleFontSize - borderTextAdjust);
ctx.font = `normal 600 ${adSubTitleFontSize}px ${fontFamily}`;
ctx.fillText(`${this.dynamicLink.qrParams.subTitleText}`, imgFrameWidth / 2, 140 + adSubTitleFontSize - borderTextAdjust);
} else {
ctx.fillText(`${this.dynamicLink.qrParams.titleText}`, imgFrameWidth / 2, 75 + adjTitleFontSize - borderTextAdjust);
}
ctx.font = `normal 700 ${adjCtaFontSize}px ${fontFamily}`;
ctx.fillText(`${this.dynamicLink.qrParams.ctaText}`, imgFrameWidth / 2, 1297 + adjCtaFontSize + borderTextAdjust);
const imgBgB64 = (img1 as any).toDataURL("image/jpeg");
const b64 = await mergeImages([
{
src: imgBgB64,
x: 0,
y: 0
},
{
src: imgQrB64,
x: qrX,
y: qrY
},
]);
// preview
element.src = b64
if (download) {
// console.log('b64', b64)
const fileName = `${this.tenant.name}-qr-code-${this.dynamicLink.name}.png`;
const blobOutput = convertBase64ToFile(b64, fileName);
saveAs(blobOutput, fileName);
}
}
In my case, I solved it by adding it to the SVG. But it's a very ugly workaround...
Adding this after qrCode.update(optionsToUpdate)
:
setTimeout(() => {
ref.current.lastChild.innerHTML += `<g fill="${color}"><text font-size="14" x="0" y="350">${text}</text></g>`;
}, 0);
I had to set a timeout to 0
to wait for the qrCode.update
to update the ref.current
...
And then instead of qrCode.download
I did my implementation through the SVG.
do you have some example of the final code?
If you would like to add a border, my app can do that for you, it uses qr-code-styling under the hood
Is it possible to add text and a border?
I would like to add the text "Join Now". It is good practice for QR codes to have a call to action and a border.
See attached. Top is the qr-code-styling one from my code and underneath is one I manually generated using an online tool.
Ideally I need the text on the qr-code-styling one.