feat: rozostup pismen vo vrstvach cenovky, tesnejsie pismeno za l/t/d s makcenom
Sablony Super cena: zlava a % podla navrhu (-0.03 / -0.02 em). Pridane sablony Super vyhodne | Oranzova (| SK). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cec8764905
commit
e2e9a82094
4 files changed
+22
-6
No files matched your search
@@ -36,6 +36,8 @@ ASSETS = {
|
|||||||
'Asset 7.svg': ('SUPER VÝHODNÉ', 'cervena', ''),
|
'Asset 7.svg': ('SUPER VÝHODNÉ', 'cervena', ''),
|
||||||
'Asset 8.svg': ('SUPER CENA', 'oranzova', ''),
|
'Asset 8.svg': ('SUPER CENA', 'oranzova', ''),
|
||||||
'Asset 9.svg': ('SUPER VÝHODNÉ', 'zelena', ''),
|
'Asset 9.svg': ('SUPER VÝHODNÉ', 'zelena', ''),
|
||||||
|
'Asset 10.svg': ('SUPER VÝHODNÉ', 'oranzova', 'SK'),
|
||||||
|
'Asset 11.svg': ('SUPER VÝHODNÉ', 'oranzova', ''),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -942,6 +942,14 @@ export const BadgeEditorModal: React.FC<BadgeEditorModalProps> = ({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<NumberSlider label="Veľkosť" value={layer.fontSize || 16} min={4} max={120} onChange={(v) => updateLayer(layer.id, { fontSize: v })} />
|
<NumberSlider label="Veľkosť" value={layer.fontSize || 16} min={4} max={120} onChange={(v) => updateLayer(layer.id, { fontSize: v })} />
|
||||||
|
<NumberSlider
|
||||||
|
label="Rozostup"
|
||||||
|
value={Math.round((layer.letterSpacing || 0) * 100)}
|
||||||
|
min={-15}
|
||||||
|
max={30}
|
||||||
|
suffix=" %"
|
||||||
|
onChange={(v) => updateLayer(layer.id, { letterSpacing: v ? v / 100 : undefined })}
|
||||||
|
/>
|
||||||
|
|
||||||
<div className="flex items-center gap-1.5">
|
<div className="flex items-center gap-1.5">
|
||||||
<span className="text-[10px] font-semibold text-gray-600 w-[70px]">Farba textu</span>
|
<span className="text-[10px] font-semibold text-gray-600 w-[70px]">Farba textu</span>
|
||||||
|
|||||||
+11
-6
@@ -187,20 +187,20 @@ export function renderCleanBadgeSvg(
|
|||||||
if (priceMatch) {
|
if (priceMatch) {
|
||||||
const [tokMain, tokSub] = badgePriceParts(priceMatch[1], product);
|
const [tokMain, tokSub] = badgePriceParts(priceMatch[1], product);
|
||||||
const idx = priceMatch.index || 0;
|
const idx = priceMatch.index || 0;
|
||||||
const before = escapeXml(replaceBadgeTextVars(rawText.slice(0, idx), product));
|
const before = tightenCarons(escapeXml(replaceBadgeTextVars(rawText.slice(0, idx), product)));
|
||||||
const after = escapeXml(replaceBadgeTextVars(rawText.slice(idx + priceMatch[0].length), product));
|
const after = tightenCarons(escapeXml(replaceBadgeTextVars(rawText.slice(idx + priceMatch[0].length), product)));
|
||||||
contentSvg = `${before}${escapeXml(tokMain)}<tspan font-size="${subFontSize}px" dx="${subDx}" dy="${subDy}" font-weight="${fontWeight}">${escapeXml(tokSub)}</tspan>${after ? `<tspan dy="${revertDy}">${after}</tspan>` : ''}`;
|
contentSvg = `${before}${escapeXml(tokMain)}<tspan font-size="${subFontSize}px" dx="${subDx}" dy="${subDy}" font-weight="${fontWeight}">${escapeXml(tokSub)}</tspan>${after ? `<tspan dy="${revertDy}">${after}</tspan>` : ''}`;
|
||||||
} else if (rawText.includes('{centy}')) {
|
} else if (rawText.includes('{centy}')) {
|
||||||
const parts = rawText.split('{centy}');
|
const parts = rawText.split('{centy}');
|
||||||
const before = escapeXml(parts[0] || '');
|
const before = tightenCarons(escapeXml(parts[0] || ''));
|
||||||
const after = escapeXml(parts[1] || '');
|
const after = tightenCarons(escapeXml(parts[1] || ''));
|
||||||
contentSvg = `${before}<tspan font-size="${subFontSize}px" dx="${subDx}" dy="${subDy}" font-weight="${fontWeight}">${escapeXml(pSub)}</tspan>${after ? `<tspan dy="${revertDy}">${after}</tspan>` : ''}`;
|
contentSvg = `${before}<tspan font-size="${subFontSize}px" dx="${subDx}" dy="${subDy}" font-weight="${fontWeight}">${escapeXml(pSub)}</tspan>${after ? `<tspan dy="${revertDy}">${after}</tspan>` : ''}`;
|
||||||
} else {
|
} else {
|
||||||
contentSvg = escapeXml(replaceBadgeTextVars(rawText, product));
|
contentSvg = tightenCarons(escapeXml(replaceBadgeTextVars(rawText, product)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// data-layer-index: editor cenoviek podľa neho nájde a odmeria vrstvu na plátne
|
// data-layer-index: editor cenoviek podľa neho nájde a odmeria vrstvu na plátne
|
||||||
return `<text data-layer-index="${layerIndex}" x="${layer.x}" y="${layerY}" text-anchor="${anchor}" dominant-baseline="central" font-family="${fontFamily}" font-size="${fontSize}px" font-weight="${fontWeight}" fill="${fill}">${contentSvg}</text>`;
|
return `<text data-layer-index="${layerIndex}" x="${layer.x}" y="${layerY}" text-anchor="${anchor}" dominant-baseline="central"${layer.letterSpacing ? ` letter-spacing="${layer.letterSpacing}em"` : ''} font-family="${fontFamily}" font-size="${fontSize}px" font-weight="${fontWeight}" fill="${fill}">${contentSvg}</text>`;
|
||||||
}).join('\n ');
|
}).join('\n ');
|
||||||
|
|
||||||
return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="${vb}" width="${displayWidth}" height="${displayHeight}" style="display:block;max-width:100%;height:auto;">
|
return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="${vb}" width="${displayWidth}" height="${displayHeight}" style="display:block;max-width:100%;height:auto;">
|
||||||
@@ -261,6 +261,11 @@ export async function svgToCleanPng(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mäkčeň pri ľ, ť, ď je v písme široký – písmeno za ním trochu pritiahneme (ako v návrhoch z Illustratora)
|
||||||
|
function tightenCarons(text: string): string {
|
||||||
|
return text.replace(/([ľťď])([^\s<&])/g, '$1<tspan dx="-0.05em">$2</tspan>');
|
||||||
|
}
|
||||||
|
|
||||||
function escapeXml(unsafe: string): string {
|
function escapeXml(unsafe: string): string {
|
||||||
if (!unsafe) return '';
|
if (!unsafe) return '';
|
||||||
return unsafe
|
return unsafe
|
||||||
|
|||||||
@@ -230,6 +230,7 @@ export interface BadgeLayer {
|
|||||||
indexOffsetY?: number; // Vertikálny posun horného indexu v px (posun hore / dole)
|
indexOffsetY?: number; // Vertikálny posun horného indexu v px (posun hore / dole)
|
||||||
indexOffsetX?: number; // Horizontálny posun horného indexu v px (medzera)
|
indexOffsetX?: number; // Horizontálny posun horného indexu v px (medzera)
|
||||||
longPriceScale?: number; // zmenšenie ceny od 10 € (dvojciferné eurá), napr. 0.8; účiaria ostáva
|
longPriceScale?: number; // zmenšenie ceny od 10 € (dvojciferné eurá), napr. 0.8; účiaria ostáva
|
||||||
|
letterSpacing?: number; // rozostup písmen v em (napr. -0.03 = tesnejšie)
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BadgeTemplate {
|
export interface BadgeTemplate {
|
||||||
|
|||||||
Reference in new issue
Block a user