diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 20b15d5..65ceb75 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -78,31 +78,110 @@ const node = document.getElementById("result"); if (!node) return; - const imageElement = node.querySelector('image[clip-path]'); + const svg = node.querySelector("svg"); + if (!svg) return; - // Temporarily remove the clip-path for saving the square image - if (imageElement) { - imageElement.removeAttribute('clip-path'); + const captureAndDownload = async (filename: string) => { + const imageElement = node.querySelector("image[clip-path]"); + if (imageElement) { + imageElement.removeAttribute("clip-path"); + } + + try { + const dataUrl = await domtoimage.toPng(node, { + style: { + border: "none", + padding: "0", + margin: "0", + outline: "none", + }, + }); + const link = document.createElement("a"); + link.download = filename; + link.href = dataUrl; + link.click(); + } finally { + if (imageElement) { + imageElement.setAttribute("clip-path", "url(#circle-clip)"); + } + } + }; + + await captureAndDownload("avatar-круговой-текст.png"); + + if (!text.trim()) return; + + const circularTextPath = svg.querySelector("#text-path"); + const circularTextBg = svg.querySelector(".circle-text-bg"); + const circularText = svg.querySelector(".circle-text"); + + if (circularTextPath) (circularTextPath as HTMLElement).style.display = "none"; + if (circularTextBg) (circularTextBg as HTMLElement).style.display = "none"; + if (circularText) (circularText as HTMLElement).style.display = "none"; + + const maxWidth = 500; + const words = text.split(' '); + const lines: string[] = []; + + const measurementText = document.createElementNS("http://www.w3.org/2000/svg", "text"); + measurementText.setAttribute("class", "circle-text"); + (measurementText as SVGTextElement).style.visibility = "hidden"; + svg.appendChild(measurementText); + + const tspan = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + measurementText.appendChild(tspan); + + let currentLine = ''; + for (const word of words) { + const testLine = currentLine ? `${currentLine} ${word}` : word; + tspan.textContent = testLine; + if (tspan.getComputedTextLength() > maxWidth && currentLine) { + lines.push(currentLine); + currentLine = word; + } else { + currentLine = testLine; + } } + lines.push(currentLine); + + const computedStyle = window.getComputedStyle(measurementText); + const computedFontSize = parseFloat(computedStyle.fontSize); + const lineHeightPx = computedFontSize * 1.2; + + svg.removeChild(measurementText); + + const createTextWithWrapping = (className: string) => { + const textEl = document.createElementNS("http://www.w3.org/2000/svg", "text"); + textEl.setAttribute("class", className); + textEl.setAttribute("text-anchor", "middle"); + + const startY = 480 - ((lines.length - 1) * lineHeightPx); + textEl.setAttribute("y", String(startY)); + + lines.forEach((line, index) => { + const lineTspan = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + lineTspan.setAttribute("x", "256"); + if (index > 0) lineTspan.setAttribute("dy", "1.2em"); + lineTspan.textContent = line; + textEl.appendChild(lineTspan); + }); + return textEl; + }; + + const straightTextBg = createTextWithWrapping("circle-text-bg"); + const straightText = createTextWithWrapping("circle-text"); + + svg.appendChild(straightTextBg); + svg.appendChild(straightText); try { - const dataUrl = await domtoimage.toPng(node, { - style: { - border: "none", - padding: "0", - margin: "0", - outline: "none", - }, - }); - const link = document.createElement("a"); - link.download = "avatar.png"; - link.href = dataUrl; - link.click(); + await captureAndDownload("avatar-прямой-текст.png"); } finally { - // Restore the clip-path for the UI to keep the circle - if (imageElement) { - imageElement.setAttribute('clip-path', 'url(#circle-clip)'); - } + svg.removeChild(straightTextBg); + svg.removeChild(straightText); + if (circularTextPath) (circularTextPath as HTMLElement).style.display = ""; + if (circularTextBg) (circularTextBg as HTMLElement).style.display = ""; + if (circularText) (circularText as HTMLElement).style.display = ""; } } @@ -169,7 +248,6 @@ style="cursor: pointer" onclick={() => document.getElementById("fileInput").click()} > - {#if !image}
{/if} - {#if image}
@@ -204,8 +281,7 @@ - - {#if text} + {#if text} {text} - {/if} + {/if}
{/if} @@ -249,7 +325,7 @@ onclick={saveImage} class="px-6 py-3 bg-gradient-to-r from-purple-600 to-blue-600 text-white font-medium rounded-lg hover:opacity-90 transition-opacity disabled:opacity-50 disabled:cursor-not-allowed" > - Сохранить 512×512 + Сохранить аватары
@@ -277,7 +353,7 @@