Rounded QR code
This commit is contained in:
parent
d6ee03f4d8
commit
8ecd58b176
|
|
@ -523,7 +523,27 @@ export default function CreatePage() {
|
|||
onClick={() => {
|
||||
const svg = document.querySelector('#create-qr-preview svg');
|
||||
if (!svg) return;
|
||||
const svgData = new XMLSerializer().serializeToString(svg);
|
||||
|
||||
let svgData = new XMLSerializer().serializeToString(svg);
|
||||
|
||||
// If rounded corners, wrap in a clipped SVG
|
||||
if (cornerStyle === 'rounded') {
|
||||
const width = svg.getAttribute('width') || '200';
|
||||
const height = svg.getAttribute('height') || '200';
|
||||
const borderRadius = 20;
|
||||
|
||||
svgData = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
|
||||
<defs>
|
||||
<clipPath id="rounded-corners">
|
||||
<rect x="0" y="0" width="${width}" height="${height}" rx="${borderRadius}" ry="${borderRadius}"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g clip-path="url(#rounded-corners)">
|
||||
${svgData}
|
||||
</g>
|
||||
</svg>`;
|
||||
}
|
||||
|
||||
const blob = new Blob([svgData], { type: 'image/svg+xml' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
|
|
@ -545,6 +565,8 @@ export default function CreatePage() {
|
|||
if (!svg) return;
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (!ctx) return;
|
||||
|
||||
const img = new Image();
|
||||
const svgData = new XMLSerializer().serializeToString(svg);
|
||||
const blob = new Blob([svgData], { type: 'image/svg+xml' });
|
||||
|
|
@ -553,7 +575,25 @@ export default function CreatePage() {
|
|||
img.onload = () => {
|
||||
canvas.width = 200;
|
||||
canvas.height = 200;
|
||||
ctx?.drawImage(img, 0, 0);
|
||||
|
||||
// Apply rounded corners if needed
|
||||
if (cornerStyle === 'rounded') {
|
||||
const borderRadius = 20;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(borderRadius, 0);
|
||||
ctx.lineTo(200 - borderRadius, 0);
|
||||
ctx.quadraticCurveTo(200, 0, 200, borderRadius);
|
||||
ctx.lineTo(200, 200 - borderRadius);
|
||||
ctx.quadraticCurveTo(200, 200, 200 - borderRadius, 200);
|
||||
ctx.lineTo(borderRadius, 200);
|
||||
ctx.quadraticCurveTo(0, 200, 0, 200 - borderRadius);
|
||||
ctx.lineTo(0, borderRadius);
|
||||
ctx.quadraticCurveTo(0, 0, borderRadius, 0);
|
||||
ctx.closePath();
|
||||
ctx.clip();
|
||||
}
|
||||
|
||||
ctx.drawImage(img, 0, 0);
|
||||
canvas.toBlob((blob) => {
|
||||
if (blob) {
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
|
@ -564,6 +604,7 @@ export default function CreatePage() {
|
|||
URL.revokeObjectURL(url);
|
||||
}
|
||||
});
|
||||
URL.revokeObjectURL(url);
|
||||
};
|
||||
img.src = url;
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -354,10 +354,9 @@ export default function SettingsPage() {
|
|||
<Button
|
||||
variant="outline"
|
||||
className="w-full"
|
||||
onClick={handleManageSubscription}
|
||||
disabled={loading}
|
||||
onClick={() => window.location.href = '/pricing'}
|
||||
>
|
||||
{loading ? 'Loading...' : 'Manage Subscription'}
|
||||
Manage Subscription
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,26 @@ END:VCARD`;
|
|||
if (!svg) return;
|
||||
|
||||
if (format === 'svg') {
|
||||
const svgData = new XMLSerializer().serializeToString(svg);
|
||||
let svgData = new XMLSerializer().serializeToString(svg);
|
||||
|
||||
// If rounded corners, wrap in a clipped SVG
|
||||
if (qr.style?.cornerStyle === 'rounded') {
|
||||
const width = svg.getAttribute('width') || '96';
|
||||
const height = svg.getAttribute('height') || '96';
|
||||
const borderRadius = 10; // Smaller radius for dashboard
|
||||
|
||||
svgData = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
|
||||
<defs>
|
||||
<clipPath id="rounded-corners-${qr.id}">
|
||||
<rect x="0" y="0" width="${width}" height="${height}" rx="${borderRadius}" ry="${borderRadius}"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g clip-path="url(#rounded-corners-${qr.id})">
|
||||
${svgData}
|
||||
</g>
|
||||
</svg>`;
|
||||
}
|
||||
|
||||
const blob = new Blob([svgData], { type: 'image/svg+xml' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
|
|
@ -96,15 +115,35 @@ END:VCARD`;
|
|||
// Convert SVG to PNG
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (!ctx) return;
|
||||
|
||||
const img = new Image();
|
||||
const svgData = new XMLSerializer().serializeToString(svg);
|
||||
const blob = new Blob([svgData], { type: 'image/svg+xml' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
||||
|
||||
img.onload = () => {
|
||||
canvas.width = 300;
|
||||
canvas.height = 300;
|
||||
ctx?.drawImage(img, 0, 0, 300, 300);
|
||||
|
||||
// Apply rounded corners if needed
|
||||
if (qr.style?.cornerStyle === 'rounded') {
|
||||
const borderRadius = 30; // Scale up for 300px canvas
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(borderRadius, 0);
|
||||
ctx.lineTo(300 - borderRadius, 0);
|
||||
ctx.quadraticCurveTo(300, 0, 300, borderRadius);
|
||||
ctx.lineTo(300, 300 - borderRadius);
|
||||
ctx.quadraticCurveTo(300, 300, 300 - borderRadius, 300);
|
||||
ctx.lineTo(borderRadius, 300);
|
||||
ctx.quadraticCurveTo(0, 300, 0, 300 - borderRadius);
|
||||
ctx.lineTo(0, borderRadius);
|
||||
ctx.quadraticCurveTo(0, 0, borderRadius, 0);
|
||||
ctx.closePath();
|
||||
ctx.clip();
|
||||
}
|
||||
|
||||
ctx.drawImage(img, 0, 0, 300, 300);
|
||||
canvas.toBlob((blob) => {
|
||||
if (blob) {
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
|
@ -166,13 +205,15 @@ END:VCARD`;
|
|||
</div>
|
||||
|
||||
<div id={`qr-${qr.id}`} className="flex items-center justify-center bg-gray-50 rounded-lg p-4 mb-3">
|
||||
<QRCodeSVG
|
||||
value={qrUrl}
|
||||
size={96}
|
||||
fgColor={qr.style?.foregroundColor || '#000000'}
|
||||
bgColor={qr.style?.backgroundColor || '#FFFFFF'}
|
||||
level="M"
|
||||
/>
|
||||
<div className={qr.style?.cornerStyle === 'rounded' ? 'rounded-lg overflow-hidden' : ''}>
|
||||
<QRCodeSVG
|
||||
value={qrUrl}
|
||||
size={96}
|
||||
fgColor={qr.style?.foregroundColor || '#000000'}
|
||||
bgColor={qr.style?.backgroundColor || '#FFFFFF'}
|
||||
level="M"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2 text-sm">
|
||||
|
|
|
|||
Loading…
Reference in New Issue