Rozkład okręgów SVG na ścieżki
Opublikowany: 2022-03-10Ten artykuł zaczyna się od wyznania: lubię ręcznie kodować SVG. Nie zawsze tak jest, ale dość często może wydawać się dziwne dla osób, które nie podzielają mojego upodobania. Możliwość ręcznego pisania SVG ma wiele zalet, takich jak optymalizacja SVG w sposób, którego nie potrafi narzędzie (przekształcenie ścieżki w prostszą ścieżkę lub kształt) lub po prostu zrozumienie, jak działają biblioteki takie jak D3 lub Greensock .
Powiedziawszy to, chciałbym dokładniej przyjrzeć się okrągłym kształtom w SVG i rzeczom, które możemy z nimi zrobić, gdy przejdziemy poza podstawowy okrąg. Dlaczego kręgi? Cóż, kocham kręgi. To mój ulubiony kształt.
Po pierwsze (mam nadzieję, że widziałeś już podstawowy okrąg w SVG), oto pióro, które pokazuje jeden:
Z okręgiem można zrobić wiele rzeczy: można go animować i można do niego nałożyć różne kolory. Mimo to są dwie bardzo fajne rzeczy, których nie możesz zrobić w SVG 1.1 za pomocą koła: nie możesz sprawić, by inny element graficzny poruszał się po ścieżce okręgu (za pomocą elementu animateMotion
) i nie możesz kształtować tekstu wzdłuż ścieżki okręgu (to spowoduje dozwolone tylko po wydaniu SVG 2.0).
Zmieniając nasz krąg w ścieżkę
Istnieje małe narzędzie online, które może pomóc w tworzeniu ścieżek poza kręgami (możesz je wypróbować tutaj), ale zamierzamy tworzyć wszystko od zera, abyśmy mogli dowiedzieć się, co naprawdę dzieje się za kulisami.
Aby stworzyć okrągłą ścieżkę, zrobimy właściwie dwa łuki, czyli półkola, które uzupełniają okrąg w jednej ścieżce. Jak zapewne zauważyłeś w powyższym SVG, atrybuty CX
, CY
i R
definiują odpowiednio miejsce narysowania okręgu wzdłuż osi X i Y, podczas gdy R
określa promień okręgu. CX
i CY
tworzą środek okręgu, więc okrąg jest rysowany wokół tego punktu.
Replikacja tego okręgu może wyglądać tak:
<path d=" M (CX - R), CY a R,R 0 1,0 (R * 2),0 a R,R 0 1,0 -(R * 2),0 " />
Zauważ, że CX
jest tym samym, co atrybut cx
okręgu; to samo dotyczy CY
i atrybutu cy
koła, a także R
i atrybutu r
koła. Mały a
jest używany do zdefiniowania segmentu łuku eliptycznego. Możesz użyć opcjonalnego Z
(lub z
), aby zamknąć ścieżkę.
Mała litera a
oznacza początek łuku eliptycznego narysowanego względem aktualnej pozycji — lub w naszym konkretnym przypadku:
<path d=" M 25, 50 a 25,25 0 1,1 50,0 a 25,25 0 1,1 -50,0 " />
Możesz zobaczyć magię dziejącą się w tym długopisie:
Pod ścieżką ukryty jest okrąg z czerwonym wypełnieniem. Gdy będziesz bawić się wartościami ścieżki, zobaczysz ten okrąg, o ile ścieżka całkowicie obejmuje okrąg (sama ścieżka jest kołem o tym samym rozmiarze) i będziemy wiedzieć, że robimy rzeczy dobrze .
Jedną rzeczą, którą powinieneś również wiedzieć, jest to, że dopóki rysujesz względne łuki, nie musisz powtarzać polecenia a
każdego narysowanego łuku. Kiedy pierwsze 7 wejść zostanie wykonanych dla łuku, drugie 7 wejść zostanie pobranych dla następnego łuku.
Możesz to wypróbować za pomocą pióra powyżej, usuwając drugie a
na ścieżce:
a 25,25 0 1,1 50,0 25,25 0 1,1 -50,0
Może to wyglądać tak samo, ale wolę to zostawić, dopóki nie będę gotowy do ukończenia rysunku, a to pomaga mi również śledzić, gdzie jestem.
Jak działa ta ścieżka?
Najpierw przechodzimy do absolutnie pozycjonowanej współrzędnej X,Y
na obrazie. Niczego tam nie rysuje — po prostu się tam porusza. Pamiętaj, że dla elementu okręgu CX
CY
oznacza środek okręgu; ale jak to się dzieje w łuku eliptycznym, prawdziwe CX
i CY
łuku zostaną obliczone na podstawie innych właściwości tego łuku.
Innymi słowy, jeśli chcemy, aby nasz CX
był równy 50
, a nasz promień to 25
, musimy przejść do 50 - 25
(jeśli oczywiście rysujemy od lewej do prawej). Oznacza to, że nasz pierwszy łuk jest rysowany od 25 X, 50 Y
co powoduje, że nasz pierwszy łuk ma 25,25 0 1,0 50,0
.
Załóżmy, co właściwie oznacza wartość 25,25 0 1,0 50,0
naszego łuku:
-
25
: Względny promień X łuku; -
25
: Względny promień Y łuku; -
0 1,0
: Nie będę mówił o trzech środkowych wartościach (obrót, flaga dużego łuku i właściwości flagi przeciągnięcia), ponieważ nie są one bardzo ważne w kontekście obecnego przykładu, o ile są są takie same dla obu łuków; -
50
: Końcowa współrzędna X (względna) łuku; -
0
: Końcowa współrzędna Y (względna) łuku.
Drugi łuk to 25,25 0 1,0 -50,0
. Pamiętaj, że ten łuk zacznie rysować od miejsca, w którym zakończył się ostatni łuk. Oczywiście promień X i Y są takie same ( 25
), ale końcowa współrzędna X to -50
od aktualnej.
Oczywiście ten krąg można było narysować na wiele różnych sposobów. Ten proces zamieniania koła w ścieżkę nazywa się rozkładem. W specyfikacji SVG 2 dekompozycja okręgu będzie wykonywana za pomocą 4 łuków, jednak zalecana przez nią metoda nie jest jeszcze możliwa do użycia, ponieważ obecnie zależy od funkcji zwanej ścieżką zamykającą segment, która nie została jeszcze określona.
Aby pokazać Wam, że okrąg możemy narysować na wiele sposobów, przygotowałem mały długopis z różnymi przykładami:
Jeśli przyjrzysz się bliżej, zobaczysz nasz oryginalny okrąg wraz z pięcioma różnymi przykładami rysowania ścieżek na tym okręgu. Każda ścieżka ma element potomny desc
opisujący użycie wartości CX
, CY
i R
do zbudowania koła. Pierwszy przykład to ten, który omówiliśmy tutaj, podczas gdy trzy inne używają odmian, które powinny być zrozumiałe po przeczytaniu kodu; ostatni przykład używa czterech łuków półkolistych zamiast dwóch, co nieco powiela proces opisany w specyfikacji SVG 2 połączonej powyżej.
Okręgi są nakładane na siebie warstwami przy użyciu naturalnego indeksowania Z SVG polegającego na umieszczaniu elementów, które pojawiają się później w znacznikach, na tych, które pojawiają się wcześniej.
Jeśli klikniesz okrągłe ścieżki w pisaku, pierwsze kliknięcie spowoduje wydrukowanie struktury ścieżki w konsoli i dodanie klasy do elementu, dzięki czemu zobaczysz kolor obrysu tego, jak narysowany jest okrąg (możesz zobaczyć że pierwszy okrąg jest narysowany klinem początkowym od uderzenia). Drugie kliknięcie spowoduje usunięcie kręgu, dzięki czemu będziesz mieć możliwość interakcji z kręgiem poniżej.
Każde koło ma inny kolor wypełnienia; rzeczywisty element koła jest żółty i po każdym kliknięciu wyświetli się komunikat „Kliknąłeś koło”. Możesz też oczywiście po prostu przeczytać kod, ponieważ elementy desc
są dość proste.
Idąc ze ścieżki do kręgu
Przypuszczam, że zauważyłeś, że chociaż istnieje wiele różnych sposobów rysowania okręgu, użyte ścieżki nadal wyglądają dość podobnie. Często — zwłaszcza w plikach SVG wyjściowych programu do rysowania — okręgi będą reprezentowane przez ścieżki. Wynika to prawdopodobnie z optymalizacji kodu programu graficznego; gdy masz kod do narysowania ścieżki, możesz narysować wszystko, więc po prostu tego użyj. Może to prowadzić do nieco rozdętych plików SVG, które są trudne do zrozumienia.
Zalecana literatura : „ Wskazówki dotyczące tworzenia i eksportowania lepszych plików SVG do Internetu” autorstwa Sary Soueidan
Jako przykład weźmy następujący SVG z Wikipedii. Kiedy spojrzysz na kod tego pliku, zobaczysz, że ma on dużo edytora po przejściu przez SVGOMG Jake'a Archibalda! (o czym możesz przeczytać więcej tutaj), otrzymasz coś takiego jak następujący plik, który został całkiem zoptymalizowany, ale kręgi w dokumencie są nadal renderowane jako ścieżki:
Zobaczmy więc, czy możemy dowiedzieć się, jakie powinny być te koła, gdyby były rzeczywistymi elementami okręgów, biorąc pod uwagę to, co wiemy o działaniu ścieżek. Pierwsza ścieżka w dokumencie oczywiście nie jest kołem, podczas gdy dwie następne są (pokazują tylko atrybut d
):
M39 20a19 19 0 1 1-38 0 19 19 0 1 1 38 0z
M25 20a5 5 0 1 1-10 0 5 5 0 1 1 10 0z
Więc pamiętając, że drugie a
można pominąć, przepiszmy je, aby miały trochę więcej sensu. (Pierwsza ścieżka to duże koło.)
M39 20 a19 19 0 1 1-38 0 a19 19 0 1 1 38 0z
Te łuki są więc oczywiście następujące:
aR R 0 1 1 - (R * 2) 0 aR R 0 1 1 (R * 2) 0
Oznacza to, że nasz promień okręgu wynosi 19
, ale jakie są nasze wartości CX
i CY
? Myślę, że nasza M39
to w rzeczywistości CX + R
, co oznacza, że CX
to 20
i CY
też to 20
.
Załóżmy, że dodajesz w kółku po wszystkich ścieżkach takich jak ta:
<circle fill="none" stroke-width="1.99975" stroke="red" r="19" cx="20" cy="20" />
Zobaczysz, że to prawda i że czerwone obrysowane koło pokrywa dokładnie to duże koło. Przeformułowana ścieżka drugiego koła wygląda tak:
M25 20 a5 5 0 1 1-10 0 5 5 0 1 1 10 0z
Oczywiście promień wynosi 5
i założę się, że nasze wartości CX
i CY
są takie same jak poprzednio: - 20
.
Uwaga : Jeśli CX = 20
, to CX + R = 25
. Okrąg znajduje się wewnątrz większego w środku, więc oczywiście powinien mieć te same wartości CX
i CY
.
Dodaj następujący okrąg na końcu ścieżek:
<circle fill="yellow" r="5" cx="20" cy="20" />
Możesz teraz zobaczyć, że jest to poprawne, patrząc na następujący długopis:
Teraz, gdy wiemy, jakie powinny być kręgi, możemy usunąć te niepotrzebne ścieżki i faktycznie utworzyć kręgi — jak widać tutaj:
Korzystanie z naszej ścieżki okrężnej do zawijania tekstu
Więc teraz, gdy mamy nasze kręgi na ścieżkach, możemy zawijać tekst na tych ścieżkach. Poniżej znajduje się pióro z tymi samymi ścieżkami, co nasze poprzednie pióro „Wszystkie koła”, ale z tekstem zawiniętym na ścieżce. Za każdym razem, gdy klikniesz ścieżkę, ta ścieżka zostanie usunięta, a tekst zostanie zawinięty na następnej dostępnej ścieżce, na przykład:
Patrząc na różne ścieżki, zauważysz niewielkie różnice między każdą z nich (więcej o tym za chwilę), ale najpierw można zauważyć niewielką niezgodność między przeglądarkami — szczególnie zauważalną na pierwszej ścieżce:
Programista Firefoksa | |
Chrom | |
Microsoft Edge |
Powodem, dla którego początkowe „S” od „Smashing” znajduje się pod tym dziwnym kątem w rozwiązaniu Firefox, jest to, że to właśnie tam zaczęliśmy rysować naszą ścieżkę (ze względu na użyte polecenie vR). Jest to bardziej widoczne w wersji Chrome, gdzie wyraźnie widać pierwszy narysowany przez nas klin w kształcie koła:
Chrome nie podąża za wszystkimi klinami, więc jest to wynik, gdy zmienisz tekst na „Smashing Magazine”. |
Powodem jest to, że Chrome ma błąd dotyczący dziedziczenia atrybutu textLength
zadeklarowanego na nadrzędnym elemencie text
. Jeśli chcesz, aby oba wyglądały tak samo, umieść atrybut textLength
zarówno w elemencie textPath
, jak i w tekście. Czemu? Ponieważ okazuje się, że Firefox Developer ma ten sam błąd, jeśli atrybut textLength
nie jest określony w elemencie text
(tak dzieje się od kilku lat).
Microsoft Edge ma zupełnie inny błąd; nie może obsłużyć spacji między elementem Text
a elementem potomnym TextPath
. Po usunięciu białych znaków i umieszczeniu atrybutu textLength
zarówno w elemencie text
, jak i textPath
, wszystkie będą wyglądać względnie tak samo (z małymi zmianami wynikającymi z różnic w domyślnych czcionkach i tak dalej). A więc trzy różne błędy w trzech różnych przeglądarkach — dlatego ludzie często wolą pracować z bibliotekami!
Poniższy długopis pokazuje, jak można rozwiązać problemy:
Usunąłem również różne kolory wypełnienia, ponieważ ułatwia to zobaczenie zawijania tekstu. Usunięcie kolorów wypełnienia oznacza, że moja mała funkcja umożliwiająca przechodzenie przez ścieżki i sprawdzanie, jak wyglądają, nie zadziała, chyba że dodam atrybut pointer-events="all"
, więc je również dodałem.
Uwaga : Możesz przeczytać więcej o przyczynach tego w „Zarządzanie interakcją SVG z właściwością zdarzeń wskaźnika” wyjaśnioną przez Tiffany B. Brown.
Omówiliśmy już zawijanie ścieżki wielołukowej, więc spójrzmy teraz na inne. Ponieważ mamy jedną ścieżkę, po której się zawijamy, tekst zawsze będzie poruszał się w tym samym kierunku.
Obraz | Ścieżka | Wyjaśnienie |
---|---|---|
M CX, CY a R, R 0 1,0 -(R * 2), 0 a R, R 0 1,0 R * 2, 0 i używa funkcji translate , aby przesunąć +R na osi X. | Pozycja początkowa dla naszego textPath (ponieważ nie określiliśmy jej w żaden sposób) jest określona przez nasz pierwszy końcowy łuk -(R * 2) , biorąc pod uwagę promień samego łuku. | |
M (CX + R), CY a R,R 0 1,0 -(R * 2),0 a R,R 0 1,0 (R * 2),0 | To samo dotyczy poprzedniej ścieżki. | |
M CX CY m -R, 0 a R,R 0 1,0 (R * 2),0 a R,R 0 1,0 -(R * 2),0 | Ponieważ kończymy na (R * 2 ) w naszym pierwszym łuku, oczywiście zaczniemy od przeciwnej pozycji. Innymi słowy, ta zaczyna się tam, gdzie kończyły się nasze dwie poprzednie ścieżki. | |
M (CX - R), CY a R,R 0 1, 1 (R * 2),0 a R,R 0 1, 1 -(R * 2),0 | Rozpoczyna się w tej samej pozycji co ostatnia z powodu (R * 2) , ale działa zgodnie z ruchem wskazówek zegara, ponieważ ustawiliśmy właściwość flagi przemiatania (zaznaczona na żółto) na 1 . |
Widzieliśmy, jak zawijać tekst na jednej ścieżce w okręgu. Przyjrzyjmy się teraz, jak możemy podzielić tę ścieżkę na dwie ścieżki i jakie korzyści można z tego uzyskać.
Dzielenie naszych ścieżek na części
Jest wiele rzeczy, które możesz zrobić z tekstem na swojej ścieżce, np. uzyskać efekty stylistyczne za pomocą elementów tspan
, ustawić przesunięcie tekstu lub animować tekst. Zasadniczo cokolwiek zrobisz, będzie ograniczone samą ścieżką. Ale dzieląc nasze wielołukowe ścieżki na pojedyncze ścieżki łukowe, możemy bawić się kierunkiem naszego tekstu, indeksowaniem Z różnych części naszego tekstu i osiągać bardziej złożone animacje.
Najpierw będziemy chcieli użyć innego obrazu SVG, aby pokazać niektóre efekty. Będę używał diamentu z artykułu o wydarzeniach wskaźnikowych, o których wspomniałem wcześniej. Najpierw pokażmy, jak będzie wyglądać z umieszczonym na nim okrągłym tekstem o pojedynczej ścieżce.
Załóżmy, że nasz okrąg to CX 295, CY 200, R 175
. Teraz, postępując zgodnie z metodą ścieżki kołowej, widzimy teraz:
M (CX - R), CY a R,R 0 1,1 (R * 2),0 a R,R 0 1,1 -(R * 2),0
Nie będę mówił o ścieżce ani rozmiarze tekstu, kolorze wypełnienia lub obrysu. Wszyscy powinniśmy już to zrozumieć i być w stanie sprawić, by było to, czym chcemy. Ale patrząc na tekst, od razu widzimy pewne wady lub ograniczenia:
- Cały tekst biegnie w jednym kierunku;
- Może fajnie byłoby mieć część tekstu za ametystem, zwłaszcza tam, gdzie jest napisane MAGAZYN. Aby litery „M” i „E” były ustawione w kole, „A” musi znajdować się z boku dolnego punktu ametystu, co jest w pewnym sensie niezrównoważone w inny sposób. (Uważam, że „A” powinno być precyzyjnie ustawione i skierowane w tym miejscu.)
Jeśli chcemy naprawić te problemy, musimy podzielić naszą pojedynczą ścieżkę na dwie. W poniższym pisaku podzieliłem ścieżkę na dwie ścieżki (i umieściłem je w obszarze defs
SVG, aby nasze textPath
s do odniesienia):
Ponownie, zakładając, że nasze CX
to 295, CY 200, R 175
, wtedy dwie ścieżki mają następujący format (dla górnej półkolistej ścieżki):
M (CX - R), CY a R,R 0 1,1 (R * 2),0
A na dole:
M (CX + R), CY a R,R 0 1,1 -(R * 2),0
Jednak nadal mamy okrągły tekst, który porusza się w tym samym kierunku. Aby to naprawić dla wszystkiego oprócz Edge, wystarczy dodać atrybut side="right"
do elementu text
, który przechowuje textPath
'MAGAZINE'.
Sprawianie, że tekst idzie w innym kierunku
Jeśli chcemy obsługiwać jak najwięcej przeglądarek, musimy zmienić ścieżkę i nie polegać na atrybucie side
, który nie jest w pełni obsługiwany. To, co możemy zrobić, to skopiować naszą górną ścieżkę półokręgu, ale zmienić przeciągnięcie z 1
na 0
:
Zanim:
M 120, 200 a 175,175 0 1,
M 120, 200 a 175,175 0 1,
1
350,0
350,0
Później:
M 120, 200 a 175,175 0 1,
M 120, 200 a 175,175 0 1,
0
350,0
350,0
Ale nasz tekst jest teraz rysowany na wewnętrznym okręgu zdefiniowanym przez przeciągnięcie i nie będzie wyglądał tak ładnie w różnych przeglądarkach. Oznacza to, że będziemy musieli przesunąć pozycję naszej ścieżki, aby zrównać się z „S” z „Rozbijania”, zwiększyć końcowy X ścieżki i ustawić pewne przesunięcie względem tekstu. Jak widać, istnieje również niewielka różnica w tekście między Firefoksem a innymi, którą możemy poprawić, zwiększając atrybut textLength
w elemencie text
, a także usuwając białe znaki z textPath
(ponieważ Firefox najwyraźniej uważa, że białe znaki są znaczące).
Rozwiązanie:
Zmień indeks Z części naszego okrągłego tekstu
Na koniec chcemy, aby nasz tekst szedł zarówno przed, jak i za ametystem. Cóż, to proste. Pamiętasz, że indeksowanie elementów w SVG jest oparte na tym, gdzie się znajdują w znacznikach? Więc jeśli mamy dwa elementy, element 1
zostanie narysowany za elementem 2
. Następnie wszystko, co musimy zrobić, to przenieść element text
w górę w naszym znaczniku SVG, aby był narysowany przed ametystem.
Poniżej możesz zobaczyć wynik, w którym części słowa „MAGAZINE” są ukryte pod dolnym punktem ametystu.
Jeśli spojrzysz na znacznik, zobaczysz, że dolny półokrąg tekstu został przesunięty przed ścieżkę, która rysuje ametyst.
Animowanie części naszego kręgu
Więc teraz mamy możliwość tworzenia okrągłego tekstu, całkowicie kontrolując kierunek części naszego tekstu, umieszczając tekst w dwóch półokręgach. Można to oczywiście wykorzystać również do animacji tekstu. Tworzenie animacji SVG w różnych przeglądarkach jest tak naprawdę tematem innego artykułu (lub znacznie większej liczby artykułów). Te przykłady będą działać tylko w przeglądarkach Chrome i Firefox ze względu na użycie składni animacji SMIL zamiast klatek kluczowych CSS lub narzędzi takich jak Greensock. Ale daje dobry wskaźnik efektów, które można osiągnąć, animując rozłożony okrąg.
Weź następujący wstrzykiwacz:
Aby zobaczyć animację w akcji, naciśnij przycisk „Uruchom ponownie” na pisaku kodowym. Dwie części naszego okrągłego tekstu zaczynają być animowane w tym samym czasie, ale mają inny czas trwania, więc kończą się w różnym czasie. Ponieważ textLength
atrybut textLength, umieściliśmy dwie dyrektywy animate
pod każdym tekstem — jedną dla elementu text
(aby działała Firefox) i jedną dla elementu textpath
(aby działał Chrome).
Wniosek
W tym artykule zobaczyliśmy, jak zamienić okrąg w ścieżkę iz powrotem, aby lepiej zrozumieć, kiedy musimy zoptymalizować ścieżkę, a kiedy nie. Widzieliśmy, jak przekształcenie okręgu w ścieżkę uwalnia nas od umieszczania tekstu na ścieżce kołowej, ale także jak dalej podzielić kołową ścieżkę na półokręgi i uzyskać pełniejszą kontrolę nad kierunkowością i animacją części składowych naszego okrągłego tekstu .
Dalsze czytanie na SmashingMag:
- Nowe podejście do responsywnego SVG
- Animowanie plików SVG za pomocą SVGator
- Stylizowanie i animowanie SVG za pomocą CSS
- Zarządzanie interakcją SVG z właściwością zdarzeń wskaźnika