Fonty SVG w resvg: wczytaj krój pisma, którego potrzebuje Twoja grafika
Napraw brakujący lub zastępowany tekst SVG w resvg, jawnie wskazując pliki fontów. Uruchom niewielki przykład w Node, porównaj trzy wyniki i zachowaj edytowalny plik źródłowy grafiki.
Na tej stronie
Aby niezawodnie renderować fonty SVG w resvg, przekaż rendererowi pliki fontów i użyj nazw ich rodzin w SVG. W przypadku natywnego wiązania dla Node, @resvg/resvg-js, oznacza to skonfigurowanie fontFiles; ustaw loadSystemFonts: false, gdy chcesz sprawdzić dokładnie, jakie fonty otrzymuje Twoje zadanie. Przykład dla Node w repozytorium projektu pokazuje tę konfigurację.
Plik PNG może wyglądać na kompletny, mimo że używa niewłaściwego kroju pisma. Sprawdź kształty liter nawet wtedy, gdy polecenie eksportu zakończy się powodzeniem.
Trzy zestawy fontów wejściowych, jeden SVG
Stworzyliśmy niewielki górski emblemat ze ścieżek i umieściliśmy obok niego edytowalny tekst PINE & FIELD. SVG wskazuje rodzinę Abel w odmianie o normalnej grubości. Wyrenderowaliśmy to samo źródło trzy razy przy użyciu @resvg/resvg-js 2.6.2, Node 22.19.0 i macOS arm64. W każdym przypadku wykrywanie fontów systemowych było wyłączone.
| Przekazane pliki fontów | Zaobserwowany wynik |
|---|---|
| Brak | Emblemat ze ścieżek został wyrenderowany; napis zniknął. |
| Tylko Anton | Napis został wyrenderowany wyraźnie innym, grubszym krojem. |
| Abel | Wyrenderowane zostały zamierzone cienkie litery. |

Te obserwacje dotyczą tego przykładu testowego i tej konfiguracji. Nie pozwalają ustalić, jaki font zastępczy zostanie wybrany przy użyciu innego zestawu fontów, innego wiązania lub innej wersji. Przydatny wniosek diagnostyczny jest prostszy: brak żądanej rodziny może spowodować brak tekstu albo pojawienie się pozornie poprawnego tekstu w zastępczym kroju pisma.
Wczytaj lokalny font w resvg-js
Ten przykład używa natywnego pakietu dla Node, a nie osobnego pakietu WebAssembly. Definicje typów dla wskazanej wersji tego wiązania wymieniają fontFiles, fontDirs i loadSystemFonts w opcji font.
W nowym folderze roboczym zainstaluj używaną tutaj wersję:
npm install --save-exact @resvg/resvg-js@2.6.2Pobierz Abel-Regular.ttf i towarzyszący mu plik OFL.txt z katalogu Abel w Google Fonts. Umieść oba pliki w podfolderze fonts. Abel jest udostępniany na licencji SIL Open Font License; zachowaj licencję razem z fontem, gdy rozpowszechniasz ten przykład.
Zapisz poniższy kod jako label.svg:
<svg xmlns="http://www.w3.org/2000/svg"
width="880" height="240" viewBox="0 0 880 240">
<rect width="880" height="240" fill="#f6f2e8"/>
<path d="M46 155 L96 57 L147 155 Z" fill="#176b5b"/>
<path d="M75 155 L112 88 L166 155 Z" fill="#81ab78"/>
<text x="195" y="151" font-family="Abel"
font-size="82" font-weight="400" fill="#152e29">
PINE & FIELD
</text>
</svg>Następnie zapisz render.mjs obok pliku SVG:
import { access, readFile, writeFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import { Resvg } from '@resvg/resvg-js';
const fontFile = fileURLToPath(
new URL('./fonts/Abel-Regular.ttf', import.meta.url)
);
await access(fontFile);
const svg = await readFile(new URL('./label.svg', import.meta.url));
const renderer = new Resvg(svg, {
font: {
loadSystemFonts: false,
fontFiles: [fontFile],
},
});
const png = renderer.render().asPng();
await writeFile(new URL('./label.png', import.meta.url), png);Uruchom node render.mjs. Adresy URL plików sprawiają, że ścieżki wejściowe i wyjściowe są określane względem skryptu, więc zmiana katalogu roboczego w terminalu nie zmienia tego, który font zostanie otwarty. access() zwraca bezpośredni błąd systemu plików, jeśli font nie istnieje lub jest niedostępny; nie sprawdza poprawności zawartości fontu.
Aby odtworzyć warianty kontrolne, pozostaw SVG bez zmian. Dla pierwszego wiersza użyj pustej tablicy fontFiles. Dla drugiego pobierz Anton-Regular.ttf z katalogu Anton w Google Fonts, zachowaj jego licencję i przekaż ten plik zamiast fontu Abel. Obejrzyj każdy PNG, zanim zmienisz cokolwiek innego.
Dopasuj nazwę rodziny, a nie nazwę pliku
Abel-Regular.ttf to ścieżka do pliku. Abel to rodzina wskazana w SVG. Zapis font-family="Abel-Regular.ttf" nie nakazuje rendererowi otwarcia tego pliku.
Atrybut SVG font-family przyjmuje nazwy rodzin lub rodziny ogólne, a gdy podasz ich kilka — listę uporządkowaną według priorytetu. Ma też odpowiednik w CSS: pasująca deklaracja CSS font-family ma pierwszeństwo przed atrybutem prezentacyjnym.
W przypadku własnej grafiki sprawdź łącznie trzy rzeczy:
- Rodzina: nazwa zapisana wewnątrz fontu i wskazana w SVG.
- Styl i grubość: czy przekazana odmiana odpowiada zamierzonemu wyglądowi liter.
- Znaki: czy font zawiera litery i symbole występujące w rzeczywistym napisie.
Pomyślne wykonanie readFile dowodzi tylko, że odczytano bajty. Widoczne słowo dowodzi tylko, że wyrenderowano jakieś litery. Żadne z nich nie dowodzi, że wybrana odmiana jest tą z Twojego projektu.
Szersze omówienie diagnostyki tekstu edytowalnego i tekstu zamienionego na kontury znajdziesz w artykule dlaczego fonty SVG zmieniają się po eksporcie.
Sprawdź te same dane wejściowe w środowisku eksportu
Traktuj font jako dane wejściowe zadania przetwarzającego grafikę. Dołącz wymagany plik fontu do wdrożenia lub pakietu zadania, a następnie potwierdź, że ustalona ścieżka wskazuje tam właśnie na niego. Krój pisma zainstalowany na laptopie używanym do projektowania łatwo przeoczyć podczas przygotowywania zadania na serwerze.
Zacznij od wyłączenia wykrywania fontów systemowych i jawnego wskazania najmniejszej listy fontów wystarczającej dla Twojego napisu testowego. Gdy wynik będzie poprawny, przetestuj rzeczywiste słowa, znaki interpunkcyjne, grubości i języki używane w Twojej grafice. Nasz napis z literami łacińskimi w odmianie o normalnej grubości nie sprawdza innych systemów pisma ani złożonych rodzin fontów.
Jeśli litery nadal wyglądają niewłaściwie, sprawdź źródło pod kątem nadpisujących reguł CSS i stylów zagnieżdżonych elementów <tspan>. Jeśli zarówno emblemat, jak i napis są nieoczekiwanie przycięte lub przeskalowane, zbadaj osobno granice SVG i wymiary obrazu rastrowego. Nasz przewodnik po wymiarach wyjściowych w CairoSVG omawia to rozróżnienie w innym rendererze; opisane w nim opcje są właściwe dla CairoSVG.
Gdy udostępniasz zgłoszenie błędu lub odtwarzalne zadanie eksportu, dołącz SVG, dokładną wersję wiązania, nazwy plików i wersje fontów, opcje renderera oraz obraz przedstawiający oczekiwany wynik. Podczas pakowania plików pamiętaj o uprawnieniach do dalszego rozpowszechniania fontów.
Zachowaj edytowalne źródło obok PNG
Powyższy kod zapisuje PNG. To rastrowy plik do przekazania odbiorcy; widoczne w nim litery nie są już edytowalnym tekstem SVG. Zachowaj label.svg i wejściowe pliki fontów jako źródło do przyszłych zmian treści napisu.
Jeśli odbiorca potrzebuje logo wektorowego z utrwalonym kształtem liter, przygotuj w edytorze grafiki wektorowej osobną kopię SVG z tekstem zamienionym na kontury i sprawdź ją w tym edytorze. Zachowaj plik źródłowy z edytowalnym tekstem. Nasz przewodnik po formatach plików logo wyjaśnia, jakie pliki źródłowe i pliki do przekazania odbiorcy służą poszczególnym zadaniom.
Jeśli potrzebny Ci emblemat istnieje tylko w PNG lub JPG, narzędzie PerfectVector do wektoryzacji logo może pomóc odzyskać grafikę wektorową dla tej części projektu. Sprawdź uzyskane ścieżki, usuń wszelkie niechciane litery odtworzone przez trasowanie i wpisz napis ponownie przy użyciu znanego fontu, zanim uruchomisz eksport w resvg. Wektoryzacja nie identyfikuje oryginalnego fontu ani nie przywraca edytowalnego tekstu. Przewodnik po wektoryzacji obrazów wyjaśnia, co zmienia taka konwersja.
Najczęściej zadawane pytania
Dlaczego tekst znika, gdy wyłączam fonty systemowe? W naszym teście bez fontów renderer nie otrzymał żadnej odmiany fontu dla edytowalnego napisu, więc pojawiła się tylko grafika ze ścieżek. Wczytaj odpowiedni font, wskazując go jawnie, i sprawdź jego rodzinę, styl oraz zakres obsługiwanych znaków.
Czy mogę użyć nazwy pliku fontu jako nazwy rodziny w SVG? W SVG użyj nazwy rodziny fontu. Lokalną nazwę pliku przekaż osobno przez fontFiles. Zmiana nazwy pliku fontu nie zmienia zapisanej w nim nazwy rodziny.
Czy resvg zamienia moje logo PNG na edytowalny SVG? Przedstawiony tutaj przykład renderuje SVG do PNG. Nie wektoryzuje logo rastrowego. W razie potrzeby odzyskaj emblemat przez wektoryzację, następnie dodaj edytowalny tekst i zachowaj ten SVG jako plik źródłowy.
Źródła
- resvg-js — Version 2.6.2 README — Użycie natywnego pakietu dla Node i jawne wczytywanie fontów.
- resvg-js — Version 2.6.2 type definitions — Konfiguracja fontów i API wyrenderowanego obrazu.
- MDN — SVG font-family — Listy rodzin i pierwszeństwo CSS.
- Google Fonts — Abel — Odmiana o normalnej grubości i licencja użyte dla zamierzonego napisu.
- Google Fonts — Anton — Font i licencja użyte w wariancie kontrolnym z podstawieniem fontu.
Jeśli rastrowy emblemat wstrzymuje pracę nad grafiką, zwektoryzuj grafikę logo, sprawdź jej krawędzie w edytorze i dodaj napis jako edytowalny tekst. Następnie wyrenderuj ją z jawnie wskazanym plikiem fontu i porównaj PNG z plikiem źródłowym, zanim przekażesz go odbiorcy.
Więcej z bloga

Matplotlib SVG: Zachowaj wykres i grafikę logo jako ścieżki
Wyeksportuj wykres z Matplotlib jako SVG, połącz go z osobnymi ścieżkami logo za pomocą svgutils i sprawdź plik przekazywany odbiorcy pod kątem osadzonych pikseli, rozmieszczenia i zmian czcionek.

Tekst w elemencie foreignObject SVG: napraw brakujące etykiety po eksporcie
Napraw etykiety SVG, które pojawiają się w przeglądarce, ale znikają po eksporcie. Porównaj foreignObject z natywnym tekstem, sprawdź przestrzenie nazw i zachowaj istniejącą grafikę.