Prawdziwe litery, prawdziwe kłopoty
Tekst w SVG jest prawdziwym tekstem. Da się go zaznaczyć, skopiować, znaleźć przez wyszukiwarkę, przeczytać czytnikiem ekranu i przetłumaczyć. To ogromna przewaga nad napisem wypalonym w JPG.
Jest też jedynym elementem SVG, którego wygląd zależy od komputera, na którym go oglądasz. I stąd bierze się cały ciężar tej lekcji.
Punkt zaczepienia
html
<text x="120" y="65" font-size="26">Wektor</text>
Pierwsza niespodzianka: x i y nie wskazują lewego górnego rogu, jak przy prostokącie. Wskazują początek linii bazowej — tej samej, na której siedzą litery w zeszycie w linie. Ogonki liter g, j, p wystają poniżej niej.
Niebieska kropka to punkt
x,y, przerywane linie pokazują osie. Przełącztext-anchornamiddle— tekst wyśrodkuje się względem tej kropki. Potemdominant-baselinenamiddlei dopiero wtedy napis będzie naprawdę na środku w obu osiach.
text-anchor ustawia wyrównanie poziome względem punktu: start, middle, end. dominant-baseline robi to samo w pionie. Kombinacja middle i middle to standardowy sposób na wyśrodkowanie etykiety w kółku albo w kafelku — i wart zapamiętania, bo używa się go bez przerwy.
Czego SVG nie potrafi
I teraz rzecz, która zaskakuje najbardziej: w SVG nie ma zawijania tekstu.
Długi napis nie przejdzie do następnej linii. Wyjedzie poza kadr i zostanie ucięty. Nie ma szerokości bloku, nie ma justowania, nie ma akapitów.
Są trzy obejścia:
Ręczne łamanie przez <tspan>. Każda linia to osobny znacznik z ustawionym przesunięciem w pionie:
html
<text x="20" y="40">
<tspan x="20" dy="0">Pierwsza linia</tspan>
<tspan x="20" dy="24">Druga linia</tspan>
</text>
Uwaga na powtórzone x — bez niego kolejna linia zaczęłaby się tam, gdzie skończyła się poprzednia.
<foreignObject> z HTML w środku. Wstawia zwykły blok HTML, który zawija się normalnie. Działa w przeglądarkach, ale nie w konwerterach do PDF ani w wielu narzędziach graficznych — więc nadaje się na stronę, nie do pliku, który ma krążyć.
Policzenie łamania z góry, czyli wygenerowanie <tspan> skryptem albo w narzędziu. To robi większość bibliotek do wykresów.
<tspan> przydaje się zresztą nie tylko do łamania. Pozwala wyróżnić fragment linii innym kolorem albo rozmiarem, bez rozbijania napisu na osobne elementy.
Pułapka fontów
To jest ten moment, w którym plik zaczyna wyglądać inaczej u Ciebie i u klienta.
html
<text font-family="Söhne">Nagłówek</text>
Ten zapis nie osadza kroju. On go tylko nazywa. Jeśli na komputerze odbiorcy nie ma czcionki o tej nazwie, przeglądarka podstawi zamiennik — inne proporcje, inna szerokość, rozjechany układ. Napis wyśrodkowany co do piksela nagle wystaje poza tło.
Jest gorzej, niż się wydaje. SVG osadzony przez <img> albo jako tło CSS nie widzi fontów wczytanych na stronie.Nawet jeśli w witrynie działa @font-face z tym samym krojem, grafika o nim nie wie, bo jest renderowana w izolacji. To jest najczęstszy powód, dla którego logo wygląda dobrze w edytorze i źle na stronie.
Masz trzy wyjścia.
Zostań przy krojach systemowych. sans-serif, serif, monospace albo stos systemowy. Bezpieczne, ale rezygnujesz z identyfikacji wizualnej.
Osadź font w pliku przez @font-face z czcionką zakodowaną w base64. Działa, ale plik puchnie o setki kilobajtów — a często dokładasz cały krój, żeby wyświetlić osiem liter.
Zamień tekst na krzywe. W programie graficznym to jedno polecenie: litery przestają być tekstem i stają się ścieżkami. Wygląd jest gwarantowany na każdym urządzeniu, a plik nie potrzebuje żadnego fontu.
Kiedy zamieniać na krzywe
Odpowiedź zależy od tego, czym ten tekst naprawdę jest.
Zamieniaj logo, znaki graficzne, hasła w statycznych ilustracjach, wszystko, gdzie liczy się dokładny kształt liter, a treść i tak jest jedna, niezmienna.
Nie zamieniaj etykiet na wykresach, opisów na mapach, tekstu w interfejsie i wszystkiego, co ktoś może chcieć przeczytać, zaznaczyć, przetłumaczyć albo znaleźć. Po zamianie na krzywe czytnik ekranu nie ma czego przeczytać — zostaje bezsensowny zbiór ścieżek. Rośnie też rozmiar pliku, bo każda litera to kilkanaście węzłów.
Jeśli musisz zamienić, a napis niesie treść, dopisz ją w <title> wewnątrz SVG. Wtedy przynajmniej technologie asystujące mają dostęp do sensu. O tym będzie osobna lekcja.
Tekst po ścieżce
I na koniec funkcja, dla której wiele osób w ogóle sięga po tekst w SVG.
html
<defs>
<path id="fala" d="M 20 90 C 70 20, 170 20, 220 90"/>
</defs>
<text>
<textPath href="#fala" startOffset="5%">
Tekst płynie po krzywej
</textPath>
</text>
Ścieżka jest tylko prowadnicą — tutaj rysuję ją szarą linią, żeby było widać, ale wcale nie musi być widoczna.
startOffsetprzesuwa napis wzdłuż niej, więc animowanie tej jednej wartości daje tekst wędrujący po torze.
Warto znać dwa ograniczenia. Tekst dłuższy niż ścieżka jest po prostu ucinany — nie zawija się i nie zaczyna od nowa. A przy mocno wygiętych krzywych litery na zewnętrznej stronie łuku rozjeżdżają się, bo każda obraca się wokół własnego punktu na ścieżce. Przy dużych rozmiarach czcionki bywa to widoczne i wtedy trzeba złagodzić krzywą.
To jest typowe zastosowanie w pieczęciach, odznakach, etykietach na okręgu i wykresach kołowych z podpisami wzdłuż wycinków.
Podsumowanie
xiyw<text>wskazują początek linii bazowej, nie lewy górny róg.text-anchorwyrównuje w poziomie,dominant-baselinew pionie; oba namiddlecentrują względem punktu.- SVG nie zawija tekstu — łamanie robi się ręcznie przez
<tspan>zdy. font-familytylko nazywa krój; brak czcionki u odbiorcy oznacza podstawienie i rozjechany układ.- SVG w
<img>i w tle CSS nie widzi fontów wczytanych na stronie. - Zamiana na krzywe gwarantuje wygląd, ale odbiera treść czytnikom ekranu i powiększa plik.
<textPath>prowadzi tekst wzdłuż dowolnej ścieżki;startOffsetprzesuwa go po torze.
W następnej lekcji zajmiemy się tym, co dzieje się, gdy SVG trafia na stronę — i dlaczego ikona wstawiona przez <img>nie chce zmienić koloru.
Do wypróbowania: w presecie textPath ustaw wygięcie na maksimum i podnieś rozmiar czcionki, dopisując font-size="26". Zobaczysz, jak litery na zewnętrznej stronie łuku zaczynają się rozjeżdżać — to nie błąd, tylko konsekwencja tego, że każda obraca się osobno wokół własnego punktu na krzywej.