Kolejność transformacji SVG: skalowanie i pozycjonowanie grafiki
Porównaj kolejność translate i scale w SVG na przykładzie logo z pomiarami. Użyj zagnieżdżonych grup, prześledź jeden punkt i ustaw grafikę bez zmieniania jej źródłowych ścieżek.
Na tej stronie
W przypadku atrybutu SVG transform="translate(60 25) scale(2)" punkt źródłowy jest skalowany ze współczynnikiem 2, a następnie przesuwany o 60 jednostek w poziomie i 25 w pionie podczas odwzorowania do układu współrzędnych rodzica. Odwróć listę na scale(2) translate(60 25), a to przesunięcie również zostanie podwojone. Grafika ma ten sam rozmiar, ale inną pozycję.
Gdy logo przeskakuje po zmianie rozmiaru, sprawdź listę transformacji, zanim zaczniesz edytować jego ścieżki. Przydatny układ to grupa zewnętrzna do pozycjonowania i grupa wewnętrzna do skalowania. Obie funkcje pozostają czytelne, a oryginalne współrzędne grafiki są nadal dostępne do późniejszej edycji.
Prześledź jeden punkt zamiast zgadywać kolejność
Weź punkt źródłowy (10, 10). Przy skali 2 i przesunięciu o (60, 25) obie listy dają następujące wyniki:
| Atrybut transformacji SVG | Obliczenie współrzędnych punktu | Punkt końcowy we współrzędnych rodzica |
|---|---|---|
translate(60 25) scale(2) | (10 × 2 + 60, 10 × 2 + 25) | (80, 45) |
scale(2) translate(60 25) | ((10 + 60) × 2, (10 + 25) × 2) | (140, 70) |
Oba punkty powstają z tych samych współrzędnych źródłowych. Druga lista skaluje zarówno przesunięcie, jak i grafikę. Jej pozycja końcowa różni się od pierwszej o (60, 25).
Możesz natrafić na pozornie sprzeczne opisy kolejności. Specyfikacja SVG opisuje listę jako zagnieżdżone układy współrzędnych w zapisanej kolejności: transformacja znajdująca się skrajnie po lewej staje się grupą zewnętrzną. Gdy śledzisz odwzorowanie punktu źródłowego od grupy wewnętrznej ku zewnętrznej, jako pierwsza działa na niego operacja z najbardziej wewnętrznej grupy. Definicja atrybutu transform w W3C pokazuje wprost równoważne zagnieżdżenie.
Przy obliczaniu współrzędnych punktu przechodź od funkcji najbardziej po prawej w lewo. Strukturę grup czytaj od zewnętrznej do wewnętrznej. Stosuj wybraną interpretację konsekwentnie przez całe obliczenie.
Porównaj ten sam znak złożony z dwóch części
Zapisz ten kompletny przykład jako transform-order.svg i otwórz go w przeglądarce. Grafika to autorski kwadratowy pierścień z osobnym trójkątnym akcentem. Otwór jest rzeczywistą pustą przestrzenią zdefiniowaną przez regułę wypełnienia even-odd.
<svg xmlns="http://www.w3.org/2000/svg" width="700" height="400"
viewBox="0 0 350 200">
<g id="art" transform="translate(60 25) scale(2)">
<path fill="#147d78" fill-rule="evenodd"
d="M10 10H50V50H10Z M20 20H40V40H20Z"/>
<path fill="#e5a340" d="M65 40L85 10L105 40Z"/>
</g>
</svg>Zmień tylko atrybut grupy na transform="scale(2) translate(60 25)". Znak przesunie się dalej w prawo i w dół, a jego rozmiar oraz odstęp między częściami pozostaną takie same.
Wyrenderowaliśmy w przeglądarce obie listy oraz ich odpowiednik z zagnieżdżonymi grupami. Panele porównawcze używają identycznych obszarów współrzędnych; blady znak pokazuje oryginalną geometrię. Każda czerwona kropka wskazuje miejsce, do którego trafia punkt źródłowy (10, 10).

Lokalny prostokąt ograniczający oryginalnej grafiki ma wartości x=10, y=10, width=95, height=40. Pierwszy układ daje granice we współrzędnych głównego elementu SVG: x=80, y=45, width=190, height=80. Odwrócona lista daje x=140, y=70, przy tym samym rozmiarze 190 × 80.
Te pomiary opisują ten prosty przykład testowy bez obrysu. Przykład nie zawiera animacji ani transformacji CSS. Pokazuje składanie układów współrzędnych, a nie jakość konwersji PerfectVector czy zgodność z każdym edytorem SVG.
Oddziel pozycjonowanie od rozmiaru za pomocą zagnieżdżonych grup
Zastąp oryginalną grupę tą strukturą, pozostawiając jej ścieżki bez zmian:
<g transform="translate(60 25)">
<g id="art" transform="scale(2)">
<path fill="#147d78" fill-rule="evenodd"
d="M10 10H50V50H10Z M20 20H40V40H20Z"/>
<path fill="#e5a340" d="M65 40L85 10L105 40Z"/>
</g>
</g>Taki układ odpowiada zastosowaniu translate(60 25) scale(2) do jednej grupy. Zewnętrzne przesunięcie ustawia pozycję przeskalowanego układu współrzędnych. Po zmianie wewnętrznej skali wartości zewnętrznego przesunięcia nadal wynoszą (60, 25).
Nie oznacza to, że każdy widoczny punkt pozostaje w miejscu podczas zmiany skali. Punkt oddalony od lokalnego początku układu nadal się przesuwa, ponieważ jego współrzędne są mnożone. Zanim wybierzesz przesunięcie, zdecyduj, który punkt źródłowy ma być punktem zakotwiczenia grafiki.
Załóżmy na przykład, że źródłowy narożnik pierścienia (10, 10) ma trafić do (120, 80) po przeskalowaniu ze współczynnikiem 2. Oblicz:
tx = targetX - scale × anchorX = 120 - 2 × 10 = 100
ty = targetY - scale × anchorY = 80 - 2 × 10 = 60Użyj translate(100 60) scale(2). Narożnik zostanie teraz odwzorowany do (120, 80). Przesunięcie bezpośrednio o (120, 80) umieściłoby tam lokalny początek układu, a narożnik znalazłby się dalej w prawo i w dół.
To obliczenie zakłada skalowanie równomierne bez obrotu ani pochylenia. Jeśli chcesz świadomie wybrać punkt obrotu, skorzystaj z poradnika SVG transform-origin. Umieszczaj każdą transformację w grupie odpowiedzialnej za daną funkcję, zamiast łączyć niezwiązane ze sobą poprawki metodą prób i błędów.
Odczytaj odwzorowanie po renderowaniu, gdy plik zawiera zagnieżdżenia
Zaimportowany SVG może już mieć transformacje na kilku elementach nadrzędnych. Sprawdzenie samego atrybutu najbliższej grupy pomija ich łączny efekt. Dokumentacja transform w MDN wskazuje też, że transformacja CSS ma pierwszeństwo, gdy właściwość CSS i atrybut prezentacyjny dotyczą tego samego elementu. Sprawdź obliczone style, jeśli zmiana atrybutu wydaje się nie mieć żadnego efektu.
W przypadku wyrenderowanego SVG osadzonego bezpośrednio w HTML ten fragment odwzorowuje punkt wybranej grupy do współrzędnych użytkownika głównego elementu SVG:
const root = document.querySelector('svg');
const art = document.querySelector('#art');
const rootMatrix = root.getScreenCTM();
const artMatrix = art.getScreenCTM();
if (!rootMatrix || !artMatrix) throw new Error('SVG is not measurable');
const toRoot = rootMatrix.inverse().multiply(artMatrix);
const point = new DOMPoint(10, 10).matrixTransform(toRoot);
const result = { x: point.x, y: point.y };Odwrotność macierzy głównego elementu usuwa jego wspólne odwzorowanie na ekran. To istotne, ponieważ rozmiar wyświetlania przykładu 700 × 400 jest dwukrotnie większy niż jego viewBox 350 × 200. Piksele ekranu i współrzędne SVG są tutaj różnymi jednostkami. MDN dokumentuje odwzorowanie zwracane przez getScreenCTM().
Nasze porównanie w przeglądarce dało matrix(2 0 0 2 60 25) dla pierwszej listy i wersji z zagnieżdżonymi grupami. Odwrócona lista dała matrix(2 0 0 2 120 50). W tym przykładzie skalowania i przesunięcia ostatnie dwie liczby wyraźnie pokazują różnicę w przesunięciu.
Fragment zakłada odwracalne transformacje dwuwymiarowe. Skala zerowa nie nadaje się do tej weryfikacji z użyciem macierzy odwrotnej. W przypadku nakładek, eksportów dopasowanych do grafiki, obrysów lub obróconych prostokątów skorzystaj z bardziej szczegółowej procedury wyznaczania granic SVG.
Nie oczekuj, że getBBox() wywołane na grupie grafiki zwróci jej przekształconą pozycję w głównym układzie współrzędnych. Lokalny wynik pomija transformację samego elementu oraz transformacje jego elementów nadrzędnych, co wyjaśnia dokumentacja getBBox. Lokalny prostokąt ograniczający może pozostać bez zmian, mimo że znak widocznie się przesuwa.
Popraw transformację, zanim odtworzysz grafikę
Pracuj na kopii SVG. Zidentyfikuj ścieżki, które powinny poruszać się razem, a następnie sprawdź ich grupę i jej elementy nadrzędne. Zanotuj łatwy do rozpoznania punkt zakotwiczenia oraz docelową pozycję tego punktu.
Zmieniaj jedną transformację naraz. Jeśli rozmiar jest poprawny, ale pozycja błędna, porównaj przesunięcie uzyskane przy obu kolejnościach. Jeśli części poruszają się niezależnie, umieść ich wspólne pozycjonowanie w grupie, która je zawiera. Rozpatruj punkt obrotu osobno od kwestii kolejności skalowania.
Otwórz ponownie zapisany plik w docelowym środowisku i sprawdź cały obszar zajmowany przez znak. Poprawna transformacja nadal może przesunąć grafikę poza viewBox lub do obszaru przycinania. Poradnik edycji SVG omawia szerszy proces porządkowania i eksportu.
Jeśli znak istnieje tylko jako PNG lub JPG, a potrzebujesz edytowalnych konturów, wektoryzator logo PerfectVector może przygotować wstępną wersję SVG. Sprawdź jego sylwetkę, otwór i oddzielne kształty, a następnie zgrupuj odzyskaną grafikę i zastosuj transformacje pozycjonujące w edytorze lub kodzie.
Obraz rastrowy można przesuwać i skalować bez wektoryzacji. Używaj trasowania, gdy potrzebujesz edytowalnych kształtów, i zachowaj istniejący wektorowy plik wzorcowy, jeśli go masz. Dokładna geometria logo lub liternictwo nadal mogą wymagać ręcznego odtworzenia; poradnik wektoryzacji logo wyjaśnia, jak wybrać metodę wyjściową.
FAQ
Czy SVG stosuje transformacje od lewej do prawej, czy od prawej do lewej? Lista odpowiada zagnieżdżonym układom współrzędnych w zapisanej kolejności, od zewnętrznego do wewnętrznego. Gdy obliczasz końcową pozycję punktu źródłowego, najpierw zastosuj funkcję najbardziej po prawej, a potem przechodź na zewnątrz w lewo.
Dlaczego odwrócenie kolejności translate i scale przesuwa logo? Gdy na liście transformacji zapisanej w atrybucie scale występuje przed translate, skala mnoży również przesunięcie. Gdy translate występuje przed scale, przesunięcie pozostaje poza tym skalowaniem. Te same wartości mogą więc dać jednakowe rozmiary przy różnych pozycjach.
Czy zewnętrzne przesunięcie utrzyma każdy punkt w miejscu, gdy zmienię rozmiar grupy wewnętrznej? Nie. Wartości zewnętrznego przesunięcia pozostają niezależne od wewnętrznej skali. Punkty oddalone od lokalnego początku układu nadal poruszają się podczas skalowania. Wybierz punkt zakotwiczenia i oblicz przesunięcie potrzebne do umieszczenia go w wybranym miejscu.
Źródła
- W3C — SVG transform attribute — Definiuje relację między listami transformacji a zagnieżdżonymi układami współrzędnych.
- MDN — SVG transform — Dokumentuje składnię transformacji, odwzorowanie macierzowe i pierwszeństwo CSS.
- MDN — getScreenCTM — Opisuje macierz używaną do odwzorowania współrzędnych SVG do obszaru widoku dokumentu.
- MDN — getBBox — Wyjaśnia lokalne granice i pomijanie transformacji mierzonego elementu.
Jeśli Twoje źródłowe logo wymaga edytowalnej geometrii, przygotuj wstępną wersję SVG za pomocą PerfectVector, sprawdź jej kontury i oddzielne części, a następnie wybierz punkt zakotwiczenia i zweryfikuj jego końcową pozycję po skalowaniu.
Więcej z bloga

Krzywe Béziera w SVG: usuń załamanie bez dodawania węzłów
Napraw połączenie krzywych Béziera trzeciego stopnia w SVG, wyrównując ich uchwyty. Porównaj uchwyty o różnej długości i uchwyty odbite symetrycznie, poznaj polecenie S i zachowaj zamierzone narożniki.

Wyrównanie tekstu SVG w pionie: wyśrodkuj odtworzoną etykietę
Wyrównaj etykiety SVG za pomocą dominant-baseline, porównaj middle i central w dwóch fontach oraz odróżnij centrowanie ramki tekstu od widocznego kształtu liter.