feat: integrate html-to-image library for enhanced image generation and QR code rendering

This commit is contained in:
hamed
2026-07-04 22:39:33 +03:30
parent 3c019932bd
commit 39c09bfcd5
5 changed files with 131 additions and 76 deletions
+53 -9
View File
@@ -7,11 +7,38 @@ import LinkedingBlueD from "@/components/icons/LinkedingBlueD";
// Packages
import { useState } from "react";
import { toPng } from "html-to-image";
import html2canvas from "html2canvas";
import jsPDF from "jspdf";
import { Button } from "@mui/material";
import { toast } from "react-toastify";
const VAZIR_WEIGHTS = [
[400, "Vazirmatn-RD-FD-Regular.ttf"],
[500, "Vazirmatn-RD-FD-Medium.ttf"],
[600, "Vazirmatn-RD-FD-SemiBold.ttf"],
[700, "Vazirmatn-RD-FD-Bold.ttf"],
[800, "Vazirmatn-RD-FD-ExtraBold.ttf"],
];
let vazirEmbedCssPromise;
const getVazirEmbedCss = () => {
vazirEmbedCssPromise ??= Promise.all(
VAZIR_WEIGHTS.map(async ([weight, file]) => {
const res = await fetch(`/fonts/vazir/${file}`);
const blob = await res.blob();
const dataUrl = await new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(blob);
});
return `@font-face{font-family:vazir;src:url(${dataUrl});font-weight:${weight};}`;
})
).then((faces) => faces.join("\n"));
return vazirEmbedCssPromise;
};
const waitForImages = async (element) => {
const imgs = Array.from(element.querySelectorAll("img"));
await Promise.all(
@@ -43,18 +70,35 @@ function List({ hiddenRef, data, qrReady }) {
try {
await waitForImages(element);
const canvas = await html2canvas(element, {
backgroundColor: "#ffffff",
useCORS: true,
scale: 2,
imageTimeout: 15000,
});
let imgData;
let pxWidth;
let pxHeight;
const imgData = canvas.toDataURL("image/png");
try {
const fontEmbedCSS = await getVazirEmbedCss();
imgData = await toPng(element, {
pixelRatio: 2,
backgroundColor: "#ffffff",
style: { opacity: "1" },
fontEmbedCSS,
});
pxWidth = element.offsetWidth * 2;
pxHeight = element.offsetHeight * 2;
} catch {
const canvas = await html2canvas(element, {
backgroundColor: "#ffffff",
useCORS: true,
scale: 2,
imageTimeout: 15000,
});
imgData = canvas.toDataURL("image/png");
pxWidth = canvas.width;
pxHeight = canvas.height;
}
const imgWidth = 210;
const pxPerMm = canvas.width / imgWidth;
const imgHeight = canvas.height / pxPerMm;
const pxPerMm = pxWidth / imgWidth;
const imgHeight = pxHeight / pxPerMm;
const pdf = new jsPDF({
orientation: "portrait",