Add saved sign text size controls with independent QR sizing
This commit is contained in:
@@ -73,6 +73,16 @@ export function guestSignSvg(design: SignDesign, guestUrl: string, qr: SignQr) {
|
||||
.filter(([, data]) => /^data:font\/woff2;base64,[A-Za-z0-9+/=]+$/.test(data ?? ""))
|
||||
.map(([family, data]) => `@font-face{font-family:${family};src:url('${data}') format('woff2');font-weight:100 900;font-style:normal}`).join("");
|
||||
const qx = landscape ? 710 : 240, qy = landscape ? 235 : 420;
|
||||
// Keep text inside its own region; changing type never moves or shrinks the QR.
|
||||
const sizedText = (value: string, x: number, y: number, base: number, percent: number, width: number, height: number, weight = 400, centered = false) => {
|
||||
let size = base * Math.min(150, Math.max(75, Number.isFinite(percent) ? percent : 100)) / 100;
|
||||
let wrapped = signLines(value, Math.max(1, Math.floor(width / (size * .65))));
|
||||
while (wrapped.length * size * 1.25 > height && size > 8) {
|
||||
size -= .5;
|
||||
wrapped = signLines(value, Math.max(1, Math.floor(width / (size * .65))));
|
||||
}
|
||||
return wrapped.map((line, index) => `<text x="${x}" y="${y + index * size * 1.25}"${centered ? ' text-anchor="middle"' : ""} font-size="${size}" font-weight="${weight}">${escapeXml(line)}</text>`).join("");
|
||||
};
|
||||
if (design.layout) {
|
||||
const compact = design.layout === "compact";
|
||||
const photoLed = design.layout === "photo";
|
||||
@@ -100,11 +110,11 @@ export function guestSignSvg(design: SignDesign, guestUrl: string, qr: SignQr) {
|
||||
<rect width="100%" height="100%" fill="${ink}"/>
|
||||
${photo ? `<image href="${photo}" width="100%" height="100%" preserveAspectRatio="xMidYMid slice"/>` : `<text x="50%" y="50%" text-anchor="middle" fill="white" font-size="22">Add your event photo</text>`}
|
||||
</svg>` : ""}
|
||||
${lines(design.title, left, top, compact ? 25 : 19, Math.floor(column / (compact ? 15 : 11)), 500)}
|
||||
${design.titleScale === undefined ? lines(design.title, left, top, compact ? 25 : 19, Math.floor(column / (compact ? 15 : 11)), 500) : sizedText(design.title, left, top, compact ? 25 : 19, design.titleScale, column, 55, 500)}
|
||||
<g font-family="${headingFont}" fill="${headingColor}" letter-spacing="-1.8">
|
||||
${headlineLines.map((line, index) => `<text x="${left}" y="${top + 80 + index * headlineSize * 1.1}" font-size="${headlineSize}" font-weight="650">${escapeXml(line)}</text>`).join("")}
|
||||
${design.headlineScale === undefined ? headlineLines.map((line, index) => `<text x="${left}" y="${top + 80 + index * headlineSize * 1.1}" font-size="${headlineSize}" font-weight="650">${escapeXml(line)}</text>`).join("") : sizedText(design.headline, left, top + 80, fontSize, design.headlineScale, column, messageY - top - 95, 650)}
|
||||
</g>
|
||||
${lines(design.message, left, messageY, compact ? 26 : 18, compact ? (landscape ? 38 : 24) : photoLed ? (landscape ? 42 : 35) : (landscape ? 48 : 32))}
|
||||
${design.messageScale === undefined ? lines(design.message, left, messageY, compact ? 26 : 18, compact ? (landscape ? 38 : 24) : photoLed ? (landscape ? 42 : 35) : (landscape ? 48 : 32)) : sizedText(design.message, left, messageY, compact ? 26 : 18, design.messageScale, landscape && photoLed ? column : Math.min(column, qrX - left - 40), photoLed ? (landscape ? 65 : 85) : landscape ? 230 : 280)}
|
||||
<svg x="${qrX}" y="${qrY}" width="${qrSize}" height="${qrSize}" viewBox="0 0 ${qr.size + 8} ${qr.size + 8}" shape-rendering="crispEdges"><rect width="100%" height="100%" fill="white"/><path d="${qr.path}" transform="translate(4 4)" fill="black"/></svg>
|
||||
${lines("Scan to share", qrX, qrY - 22, compact ? 24 : 18, 30, 600)}
|
||||
${lines(guestUrl.replace(/^https?:\/\//, ""), qrX, qrY + qrSize + 24, compact ? 15 : 11, Math.floor(qrSize / (compact ? 9 : 7)))}
|
||||
@@ -124,10 +134,10 @@ export function guestSignSvg(design: SignDesign, guestUrl: string, qr: SignQr) {
|
||||
${design.decoration !== "minimal" ? `<rect x="35" y="35" width="${w - 70}" height="${h - 70}" rx="${design.decoration === "arch" ? 24 : 0}" fill="none" stroke="${headingInk}" stroke-opacity=".3" stroke-width="1"/>` : ""}
|
||||
<path d="M${landscape ? 90 : 85} 158h${landscape ? 470 : 680}" stroke="${headingInk}" stroke-opacity=".25" stroke-width="1"/>
|
||||
<g font-family="${headingFont}">
|
||||
${text(design.title, 108, 22, landscape ? 34 : 48, 500)}
|
||||
<g fill="${headingInk}" letter-spacing="-1.5">${text(design.headline, landscape ? 265 : 230, 52, landscape ? 18 : 24, 600)}</g>
|
||||
${design.titleScale === undefined ? text(design.title, 108, 22, landscape ? 34 : 48, 500) : sizedText(design.title, cx, 108, 22, design.titleScale, landscape ? 470 : 680, 45, 500, true)}
|
||||
<g fill="${headingInk}" letter-spacing="-1.5">${design.headlineScale === undefined ? text(design.headline, landscape ? 265 : 230, 52, landscape ? 18 : 24, 600) : sizedText(design.headline, cx, landscape ? 265 : 230, 52, design.headlineScale, landscape ? 470 : 680, landscape ? 190 : 115, 600, true)}</g>
|
||||
</g>
|
||||
${text(design.message, landscape ? 485 : 359, 19, landscape ? 40 : 60)}
|
||||
${design.messageScale === undefined ? text(design.message, landscape ? 485 : 359, 19, landscape ? 40 : 60) : sizedText(design.message, cx, landscape ? 485 : 359, 19, design.messageScale, landscape ? 470 : 680, landscape ? 85 : 55, 400, true)}
|
||||
<svg x="${qx}" y="${qy}" width="370" height="370" viewBox="0 0 ${qr.size + 8} ${qr.size + 8}" shape-rendering="crispEdges">
|
||||
<rect width="100%" height="100%" fill="white"/><path d="${qr.path}" transform="translate(4 4)" fill="black"/>
|
||||
</svg>
|
||||
|
||||
Reference in New Issue
Block a user