figmatic-print-builder/elements/QRCodeElement.jsx

95 lines
3.0 KiB
JavaScript

import { Image as KonvaImage, Transformer } from "react-konva";
import { useRef, useEffect, useState } from "react";
import useEditorStore from "../useEditorStore";
import QRCode from "qrcode";
export default function QRCodeElement({ element }) {
const updateElement = useEditorStore((state) => state.updateElement);
const setSelectedId = useEditorStore((state) => state.setSelectedId);
const selectedId = useEditorStore((state) => state.selectedId);
const shapeRef = useRef();
const trRef = useRef();
const [qrImage, setQrImage] = useState(null);
const isSelected = selectedId === element.id;
useEffect(() => {
const generateQR = async () => {
try {
const url = await QRCode.toDataURL(element.data || "https://example.com", {
width: element.size,
margin: 1,
});
const img = new window.Image();
img.src = url;
img.onload = () => {
setQrImage(img);
};
} catch (err) {
console.error("QR Code generation error:", err);
}
};
generateQR();
}, [element.data, element.size]);
useEffect(() => {
if (isSelected && trRef.current && shapeRef.current) {
trRef.current.nodes([shapeRef.current]);
trRef.current.getLayer().batchDraw();
}
}, [isSelected]);
if (!qrImage) return null;
return (
<>
<KonvaImage
ref={shapeRef}
image={qrImage}
x={element.x}
y={element.y}
width={element.size}
height={element.size}
rotation={element.rotation}
draggable
onClick={() => setSelectedId(element.id)}
onDragEnd={(e) => {
const snap = (v) => Math.round(v / 10) * 10;
updateElement(element.id, {
x: snap(e.target.x()),
y: snap(e.target.y()),
});
}}
onTransformEnd={() => {
const node = shapeRef.current;
const scaleX = node.scaleX();
node.scaleX(1);
node.scaleY(1);
updateElement(element.id, {
x: node.x(),
y: node.y(),
size: Math.max(50, node.width() * scaleX),
rotation: node.rotation(),
});
}}
/>
{isSelected && (
<Transformer
ref={trRef}
rotateEnabled={true}
boundBoxFunc={(oldBox, newBox) => {
if (newBox.width < 50 || newBox.height < 50) {
return oldBox;
}
return newBox;
}}
/>
)}
</>
);
}