PerfectVector
Autor: Irene Kim8 min czytania

Import SVG w Fabric.js: zachowaj możliwość edycji grafiki na płótnie

Importuj SVG do Fabric.js jako edytowalne obiekty, zmień kolor jednej części i wyeksportuj sprawdzoną kopię SVG. Skorzystaj z przetestowanego przykładu i odróżnij problemy pliku źródłowego od błędów API.

Na tej stronie

Aby zaimportować edytowalne SVG do Fabric.js, poczekaj na wynik loadSVGFromString() lub loadSVGFromURL(), a następnie dodaj zwrócone obiekty do płótna. Zachowaj referencję do części, którą chcesz edytować, zmień jej wypełnienie i wyeksportuj wynik za pomocą canvas.toSVG(). Wczytanie grafiki jako obrazu daje inny model edycji: zaznaczenie tego obrazu nie udostępnia każdego kolorowego obszaru jako osobnego kształtu.

To rozróżnienie ma znaczenie przy tworzeniu konfiguratora produktu, edytora odznak lub ikony z możliwością zmiany kolorów. Potrzebujesz obiektów odpowiadających częściom, które użytkownik może zmieniać. Rozszerzenie .svg nie gwarantuje takiej struktury.

Ten poradnik wykorzystuje Fabric.js 7.4.0 i niewielką, ręcznie utworzoną grafikę lampy. Sprawdza trzy kształty podczas importu, zmiany koloru i eksportu. To autorski przykład testowy zapisany w kodzie, a nie wynik konwersji w PerfectVector ani stwierdzenie, że każda funkcja SVG przetrwa te same etapy.

Wybierz model obiektów przed funkcją wczytującą

Fabric.js przetwarza SVG na własne obiekty płótna. Edytujesz je przez API Fabric; nie są to aktywne elementy DOM SVG wewnątrz płótna. Aktualna dokumentacja loadSVGFromString opisuje obietnicę zwracającą wynik parsowania oraz funkcję reviver, która otrzymuje każdy element źródłowy i utworzony dla niego obiekt.

Twoje zadaniePrzydatny punkt wyjściaCo sprawdzić przed kontynuowaniem
Zmieniaj osobne kształtyPrzetwórz SVG na obiekty FabricDocelowy obszar istnieje jako osobny obiekt
Przesuwaj całą grafikę jako jedną całośćŚwiadomie pogrupuj przetworzone obiektyEdycja i zaznaczanie obiektów wewnątrz grupy działają zgodnie z zamierzeniem
Umieść ilustrację bez edytowania jej częściSkorzystaj ze sposobu pracy z obrazemWystarczy jeden obraz, który można zaznaczyć
Zmieniaj kolory grafiki dostępnej tylko jako PNG lub JPGNajpierw przygotuj geometrię wektorowąObszary utworzone przez wektoryzację odpowiadają potrzebnym zmianom

Nie wnioskuj o strukturze obiektów na podstawie wyglądu. Dwa kolory mogą należeć do osobnych ścieżek, a kilka niepołączonych fragmentów może należeć do jednej ścieżki. Poradnik rozgrupowywania SVG wyjaśnia, jak diagnozować to w pliku źródłowym.

Uruchom mały przykład importu, zmiany koloru i eksportu

Zacznij w pustym folderze. Zainstaluj zależność w przypiętej wersji:

npm install --save-exact fabric@7.4.0

Zapisz ten kod jako index.html:

<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Fabric SVG import test</title>
<canvas id="editor" width="320" height="240"></canvas>
<button id="recolor">Recolor shade</button>
<button id="export">Export SVG</button>
<div id="output"></div>
<pre id="report"></pre>
<script type="module" src="main.js"></script>
</html>

Zapisz ten kod jako main.js. Względna ścieżka modułu pozwala uruchomić ten mały przykład bez narzędzia do pakowania modułów. W aplikacji korzystającej z takiego narzędzia zaimportuj te same nazwy z fabric.

import { Canvas, loadSVGFromString } from './node_modules/fabric/dist/index.min.mjs';
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="320" height="240" viewBox="0 0 320 240">
  <path id="shade" fill="#e6a23c" d="M115 40 H205 L230 135 H90 Z"/>
  <rect id="stem" x="151" y="135" width="18" height="57" fill="#214c54"/>
  <path id="base" fill="#214c54" d="M110 192 H210 L220 210 H100 Z"/>
</svg>`;
const canvas = new Canvas('editor', { width: 320, height: 240 });
const parts = new Map();
const parsed = await loadSVGFromString(svg, (element, object) => {
  const id = element.getAttribute('id');
  if (id) parts.set(id, object);
});
canvas.add(...parsed.objects.filter(Boolean));
canvas.requestRenderAll();
function report(exported) {
  const xml = new DOMParser().parseFromString(exported, 'image/svg+xml');
  const data = {
    version: '7.4.0',
    importedObjects: canvas.getObjects().length,
    types: canvas.getObjects().map(object => object.type),
    shadeFill: parts.get('shade').fill,
    exportedPaths: xml.querySelectorAll('path').length,
    exportedRects: xml.querySelectorAll('rect').length,
    exportedImages: xml.querySelectorAll('image').length,
  };
  document.querySelector('#report').textContent = JSON.stringify(data, null, 2);
  document.querySelector('#output').innerHTML = exported;
}
document.querySelector('#recolor').onclick = () => {
  parts.get('shade').set('fill', '#397e86');
  canvas.requestRenderAll();
  document.querySelector('#report').textContent = 'Shade recolored. Export to check delivery SVG.';
};
document.querySelector('#export').onclick = () => report(canvas.toSVG());
report(canvas.toSVG());

Udostępnij folder przez HTTP zamiast otwierać plik HTML bezpośrednio. Na przykład, jeśli masz zainstalowanego Pythona, uruchom python3 -m http.server 8000 i otwórz http://localhost:8000. Kliknij Recolor shade (zmień kolor klosza), a następnie Export SVG (eksportuj SVG). Przycisk wyświetla wyeksportowany ciąg znaków poniżej płótna; nie pobiera pliku.

Ta demonstracja wstawia do podglądu wyłącznie eksport własnego, stałego przykładu testowego. Nie wykorzystuj tego podglądu opartego na innerHTML do ogólnej obsługi przesyłanych plików SVG z niezaufanych źródeł. Przykład pomija również obsługę błędów na poziomie aplikacji i walidację plików.

Mapa przechwytuje identyfikatory źródłowe podczas parsowania. Kod zmieniający kolor odwołuje się do klosza za pomocą tej jawnej referencji, zamiast zakładać, że pierwszy zwrócony obiekt zawsze jest pożądaną częścią. W edytorze produkcyjnym zdecyduj, jak te identyfikatory i referencje będą przechowywane podczas zapisywania i ponownego otwierania dokumentu.

Co wykazał test

Nasz przykład testowy został zaimportowany jako trzy obiekty: path, rect i path. Po zmianie koloru klosza z #e6a23c na #397e86 podgląd eksportu pokazał nowy kolor klosza, podczas gdy trzon i podstawa zachowały pierwotne ciemne wypełnienie. Eksport zawierał dwie ścieżki, jeden prostokąt i żadnych elementów obrazu.

Rzeczywisty zrzut lokalnej demonstracji Fabric.js pokazujący lampę ze zmienionym kolorem na płótnie, zgodny z nią podgląd wyeksportowanego SVG oraz raport o trzech zaimportowanych obiektach i zerowej liczbie wyeksportowanych obrazów
Autentyczny zrzut ręcznie utworzonego przykładu testowego w Fabric.js 7.4.0 po zmianie koloru i eksporcie. Te obserwacje dotyczą trzech prostych kształtów przetestowanych w tym przykładzie.

Te kontrole potwierdzają, że ten przykład po eksporcie zachowuje geometrię wektorową. Nie potwierdzają zachowania oryginalnego XML, grupowania, reguł CSS ani każdej funkcji używanej przez inny plik. Zachowaj oryginalny plik główny i porównaj kopię przeznaczoną do przekazania w aplikacji, która będzie ją odbierać.

Unikaj łączenia poradników opartych na funkcjach zwrotnych z API opartym na obietnicach

Starsze przykłady często wywołują fabric.loadSVGFromString(svg, callback) i oczekują, że funkcja zwrotna otrzyma całą tablicę obiektów. W obecnym API drugi argument pełni inną rolę: jest funkcją reviver wywoływaną dla każdego obiektu. Aby otrzymać pełną kolekcję, poczekaj na wynik parsowania za pomocą await.

Poradnik migracji do wersji 6.0 wyjaśnia przejście na importy nazwane i API oparte na obietnicach. Sprawdź wersję zainstalowanego pakietu przed dostosowaniem starego fragmentu kodu; sama wymiana instrukcji importu pozostawia błędną logikę wczytywania.

Dla pliku SVG pochodzącego z tego samego źródła odpowiednim punktem wyjścia jest:

import { loadSVGFromURL } from 'fabric';
const parsed = await loadSVGFromURL('/artwork.svg');
canvas.add(...parsed.objects.filter(Boolean));
canvas.requestRenderAll();

Dokumentacja loadSVGFromURL zaznacza, że funkcja pobiera SVG i musi przestrzegać zasady tego samego źródła. Jeśli zdalny host nie zezwala na dostęp z Twojego źródła, zmiana kodu grupowania nie naprawi błędu sieciowego. Najpierw przetestuj plik udostępniany przez własną aplikację, a następnie sprawdź nieudane żądanie i konfigurację CORS zdalnego serwera.

Sprawdzaj możliwość edycji niezależnie od wyglądu

Udane renderowanie odpowiada na jedno pytanie: czy coś się pojawiło? Edytor wymaga dodatkowych kontroli.

  1. Zaznacz obszar, który ma się zmienić. Upewnij się, że inna część nie zmienia się razem z nim.
  2. Zmień kolor przez metodę set obiektu i zażądaj ponownego renderowania, tak jak w przykładzie.
  3. Wyeksportuj wynik i otwórz go niezależnie. API Canvas.toSVG generuje kod SVG na podstawie stanu płótna.
  4. Sprawdź wszystko, na czym opiera się Twoja właściwa grafika, na przykład obrysy, przycinanie, gradienty, tekst lub zagnieżdżone transformacje. Prosty przykład testowy powyżej nie sprawdza tych funkcji.
  5. Zapisz dokument, otwórz go ponownie i powtórz zamierzoną edycję we własnym edytorze, zanim uznasz proces za kompletny.

Jeśli import tworzy obiekt obrazu, sprawdź, czy źródło zawiera osadzony obraz rastrowy. Poradnik dotyczący zawartości rastrowej wewnątrz SVG pokazuje, dlaczego opakowanie w SVG nie zmienia pikseli w edytowalne ścieżki. Jeśli źródło zawiera już użyteczne kształty wektorowe, zajmij się importem i organizacją obiektów zamiast ponownie je wektoryzować.

Kiedy grafika rastrowa wymaga wcześniejszej konwersji

Jeśli Twoim jedynym źródłem jest płaski obraz PNG lub JPG, a użytkownicy muszą edytować jego kolorowe obszary, proces konwersji obrazu na grafikę wektorową w PerfectVector może pomóc przygotować plik SVG do oceny. Porównaj wynik z oryginałem, sprawdź ścieżki i upewnij się, że potrzebne obszary można edytować niezależnie, zanim zaimportujesz go do Fabric.js.

Wektoryzacja nie przypisuje znaczeń specyficznych dla aplikacji, takich jak klosz, trzon czy podstawa. Nazwy w naszym przykładzie testowym zostały nadane świadomie. Po sprawdzeniu przekonwertowanej geometrii dodaj własne mapowanie części i reguły edycji. W przypadku zestawu ikon wielokrotnego użytku poradnik konwersji PNG na SVG do zestawu elementów interfejsu omawia przygotowanie źródeł i kontrolę spójności.

Zachowaj fotografie w postaci rastrowej, jeśli mają pozostać fotografiami. Zachowaj odpowiedni oryginalny plik SVG, jeśli zawiera już potrzebne kształty. Omówienie wektoryzacji może pomóc zdecydować, czy wektoryzacja w ogóle powinna być częścią tego procesu.

Często zadawane pytania

Czy Fabric.js importuje SVG jako edytowalne ścieżki? Może przetwarzać obsługiwaną zawartość SVG na obiekty Fabric. Możliwość edycji zależy od struktury źródła: ścieżka, grupa kształtów i osadzony obraz rastrowy nie zapewniają tych samych opcji edycji. Sprawdź zwrócone obiekty i przetestuj konkretną zmianę, której potrzebujesz.

Dlaczego starszy przykład loadSVGFromString nie działa? Starsze poradniki mogą oczekiwać, że drugim argumentem będzie funkcja zwrotna wywoływana po zakończeniu wczytywania. Obecne API zwraca obietnicę i używa tego argumentu jako funkcji reviver wywoływanej dla każdego obiektu. Dopasuj kod do zainstalowanej wersji i poczekaj na wynik parsowania za pomocą await.

Czy toSVG zachowuje oryginalny plik bez żadnych zmian? Nie oczekuj identycznego dokumentu źródłowego. Ta metoda generuje SVG na podstawie stanu płótna Fabric. Zachowaj oryginalny plik główny i sprawdź wygląd eksportu oraz struktury potrzebne w procesie, do którego trafi wynik.

Czy import PNG może sprawić, że jego poszczególne obszary będą edytowalne? Umieszczenie PNG nie przekształca go w osobne obszary wektorowe. Jeśli takie zmiany są konieczne, najpierw przygotuj odpowiednią geometrię wektorową, sprawdź powstałe części i określ ich role w aplikacji.

Źródła

  1. Fabric.js — loadSVGFromString — Zwracana obietnica i zasady przekazywania elementu źródłowego oraz obiektu do funkcji reviver.
  2. Fabric.js — Upgrading to Fabric.js 6.0 — Importy nazwane i migracja z funkcji zwrotnych na obietnice.
  3. Fabric.js — loadSVGFromURL — Parsowanie SVG pobranego z adresu URL i ograniczenia pobierania wynikające z zasady tego samego źródła.
  4. Fabric.js — Canvas API — Eksport stanu płótna do kodu SVG.

Jeśli brakuje Ci edytowalnej geometrii uzyskanej z grafiki rastrowej, przygotuj plik SVG do oceny w PerfectVector. Najpierw sprawdź kształty, a następnie potwierdź, że Twój edytor Fabric.js potrafi zmienić kolor zamierzonej części i poprawnie wyeksportować wynik.

Więcej z bloga

Zacznij od czystszego SVG,
który łatwiej edytować