Czy mogę przekonwertować tekst SVG na ścieżkę, ale ponownie użyć glifów?

14

Mam plik SVG z dużą ilością tekstu. To mapa parkingu z wypisanymi na niej numerami spacji. Wyświetlam to w przeglądarce internetowej, a dzięki cudownym drobnym błędom w przeglądarce Firefox niepoprawnie renderuje tekst. Gwizd.

Więc przekonwertowałem tekst na ścieżki. Mówimy o do 4000 oddzielnych etykiet. Może teraz 15 000 nowych kształtów to teraz wektory. To 4 MB. Normalnie możesz argumentować, że to nadałoby się do kompresji, ale ja muszę wstawić SVG do HTML . Dodaję zmiany CSS dynamicznie i tylko w ten sposób mam szansę na obsługę wielu przeglądarek. Tak czy inaczej, surowa - nawet przeszukana - wydajność tego jest zbyt duża, aby była użyteczna.

Uderza mnie to, że wszystkie te liczby kosmiczne mają wspólne glify. Od zera do dziewięciu. Dlaczego dołączam definicję kształtu dla każdego wystąpienia każdej liczby? Czy mogę je zduplikować?

Korzystam z Inkscape, ale jestem otwarty na sugestie.

Oli
źródło
Czy jest szansa, że ​​możesz udostępnić plik SVG, abyśmy mogli z nim eksperymentować?
JohnB
1
Czym dokładnie jest błąd (zrzut ekranu) i jak go eksportujesz i ładujesz do przeglądarki? Istnieje duża szansa, że ​​możesz to naprawić za pomocą stylizacji CSS lub małego skryptu na stronie, aby naprawić / zamienić elementy tekstowe. Jeśli jest to dynamiczne wyświetlanie mapy, możesz zamienić ją w rzeczywistą mapę - większość bibliotek mapowania przeglądarki (i wiele opartych na danych) ma świetne wsparcie dla etykietowania.
brichins
1
Niestety, plik SVG nie jest mój do udostępnienia (należy do klienta), ale wiadomo o błędzie . Zasadniczo oznacza to, że czcionki w SVG nie skalują się poza punkt ... Co jest poważnym problemem, jeśli jesteś całkowicie powiększony na mapie z tysiącami numerowanych miejsc parkingowych. Powinny one wynosić (np.) ~ 0,08 punktu, a tak naprawdę to 13 punktów.
Oli
1
Masz zły numer błędu, jesteś rzeczywiście patrząc na ten jeden
Robert Longson
Może chcesz to przetestować na podzbiorze, ale path|simplifyw ogóle może ci pomóc? Małe litery „s” są konwertowane na ścieżkę 28-punktową, upraszczają srops na 17, a nakładanie uproszczonych i nieskomplikowanych wersji nawet powiększane, aby „s” wypełniało ekran, nie ma różnicy.
Chris H

Odpowiedzi:

6

Ten <use>element umożliwia ponowne użycie obiektów zdefiniowanych w innym miejscu w dokumencie. Na przykład możesz zdefiniować każdy glif jako a, <symbol>a następnie użyć go wiele razy. Oto ciekawy artykuł o tym: strukturyzacji, grupowanie i odniesienie w SVG - The <g>, <use>, <defs>i <symbol>Elements .

Nie wiem jednak, jak to zrobić bezpośrednio w Inkscape - szczególnie nie w przypadku fragmentu tekstu, który masz już jako tekst. Konieczne może być napisanie skryptu w celu późniejszego przetworzenia pliku SVG i znalezienia wszystkich ścieżek, które można ponownie wykorzystać.

Rahul
źródło
Właśnie o <use>tym myślałem, kiedy o to pytałem, skrypty są jak. Wydaje się głupie, że nie ma nic do zduplikowania prawie identycznych znaczników.
Oli
@Oli nie było nawet nic, co mogłoby oddzielić identyczne znaczniki; Musiałem napisać własny (i przez to samo mam na myśli bajt; haszowałem je i porównywałem hasze)
Chris H
Zastanawiałem się nad lunchem i wydaje mi się, że najlepszym rozwiązaniem będzie skrypt (python) w Inkscape. Skrypt zaczynałby się od tekstu jako tekstu i zastępowałby go odniesieniami do <symbol>s (lub wygląda na to, że możesz tworzyć <def>glify tekstu na ścieżkę
Chris H
4

Dostępnych jest kilka opcji kompresji zapewniających różne stopnie powodzenia. Aby je przetestować, stworzyłem plik grafiki, który zawierał tylko dużo powtarzającego się tekstu. Rozmiar pliku nierozwiniętego wynosi 13,8 KB. Po rozwinięciu rozmiar pliku wynosi 1,42 MB .

Dobra opcja: użyj SVGZ - 46,5 KB

Zapisanie rozwiniętej grafiki jako SVGZ dało mi plik wyjściowy 46,5 KB, który jest znacznie mniejszy niż standardowy plik SVG. Pamiętaj jednak, że wsparcie może się różnić .

Lepsza opcja: kompresuj za pomocą Scour - 21,1 KB

Scour to narzędzie, które będzie szorować i optymalizować plik SVG za Ciebie. Za pomocą polecenia „maksymalna kompresja” scour -i input.svg -o output.svgz --enable-viewboxing --enable-id-stripping --enable-comment-stripping --shorten-ids --indent=nonerozszerzonej grafiki zmniejszono do 21,1 KB. Niedaleko oryginalnego nierozwiniętego rozmiaru pliku!

JohnB
źródło
3
Szorowanie nie kompresuje, po prostu usuwa śmieci i chociaż robi dla mnie spore korzyści (biorąc pod uwagę ogromną liczbę obiektów), moje „4 MB” było po szorowaniu. Skompresowana treść byłaby świetna, ale - i powinienem o tym wspomnieć wcześniej - muszę wstawić SVG do problemów z celowaniem w przeglądarce (a także do wymagań dotyczących manipulacji nakładką). Wiem, wiem, to bolesne, ale zaufaj mi, kiedy mówię, że bolą mnie bardziej w tej chwili D:
Oli
Powinienem był powiedzieć, że część szorująca scoursię nie kompresuje. Może również wrzucić plik za pomocą gzip, ale jego głównym zadaniem jest identyfikacja i minimalizowanie białych znaków.
Oli
@Oli racja, stąd mój ostrożny wybór słowa „optymalizuj” :) To jest błąd, że twój plik jest już przeszukany ... ack!
JohnB
Pomyślałem trochę w Illustratorze; jego dane wyjściowe SVG są zgodne z symbolami. Oto szybki przykład . Zajmie to sporo wysiłku, ale możesz stworzyć skrypt programu Illustrator, który podzieli tekst na poszczególne znaki i zastąpi je symbolami. Największą przeszkodą, jaką widzę, byłaby rotacja. Jeśli cały tekst jest równoległy do ​​osi X, nie wydaje się to trudne, ale radzenie sobie z tekstem pod kątem może być wyzwaniem. Oczywiście to wszystko nie jest bardzo pomocne, jeśli nie masz programu Illustrator
JohnB
3

Jest to rozwiązanie w przeglądarce lub na serwerze

Istnieje wiele różnych sposobów optymalizacji plików SVG. Wygląda na to, że już to zrobiłeś.

Kilka zasobów, które uważam za bardzo przydatne, to artykuł z trikami css, który koncentruje się na bardzo szczegółowych szczegółach. A w szczególności narzędzie, z którego korzysta SVGO .

Jeśli masz wiele powtarzających się ścieżek, rozważę użycie javascript do dynamicznego tworzenia kształtów. Oto przykład . Jednym kierunkiem byłoby zdefiniowanie funkcji dla każdego glifu i po prostu utworzenie każdej ścieżki w elemencie svg na podstawie żądania tej funkcji. Lub weź pełny ciąg i / lub tablicę argumentów, aby utworzyć własny plik SVG. To oczywiście oczekuje, że twoje ścieżki są dłuższe niż długość kodu wymaganego do żądania wspomnianej funkcji (dość łatwe założenie).

Łukasz
źródło
1
Podczas gdy ta odpowiedź przedstawia wiele możliwych rozwiązań, SVGO wydaje się najbardziej interesujące. Można go również uruchomić na pliku .svg, aby go zoptymalizować. Jednak wydaje się, że obecnie nie wykonuje deduplikacji ścieżki. Jeśli pytający i tak skończy niestandardowe skrypty, dobrym pomysłem może być ulepszenie SVGO.
jpa
@ jpa deduplikacja przed (lub podczas) konwersji do ścieżek byłaby z pewnością droga. Zamień wszystkie wystąpienia znaku „1” na tekst <use xlink:href="#digit_one">gdzie digit_onejest ścieżka
Chris H.
@ChrisH Nie rozumiem, dlaczego nie można było równie dobrze później się dedukować. Po prostu znormalizuj wszystkie ścieżki do początku w punkcie początkowym, weź skrót, użyj go, aby sprawdzić, czy ścieżka już się wydarzyła. Jasne, nie tak eleganckie, ale powinno działać i może być łatwiejsze do wdrożenia niż konieczność ponownego wdrożenia / zrozumienia całej logiki układu tekstu.
jpa
@ jpa możesz, ale jeśli normalizacja źródła wprowadzi błędy zaokrąglania, skrót nie będzie pasował. Skrypt, o którym myślę, wywołałby tekst w ścieżce inkscape, aby ułożyć ścieżki znaków, a następnie zastąpić je odniesieniami do zestawu wzorców.
Chris H
@jpa i błędy zaokrąglania są prawdziwe. Na przykładzie zabawki pierwsza krzywa kwadratowa zera różni się o 1 w szóstym miejscu po przecinku - wystarczy, aby zepsuć haszowanie
Chris H
2

Tutaj na bardzo wysokim poziomie jest to, co powinien zrobić skrypt. Możesz swobodnie korzystać z preferowanego języka i środowiska, to tylko punkt wyjścia do logiki, która powinna dać ci to, czego szukasz.

  • Pętlę przez wszystkie elementy tekstowe w pliku XML SVG, a dla tych, które zawierają tekst numeryczny (miejsca parkingowe, nie określasz, czy jest więcej tekstu w pliku svg), zmień identyfikator automatycznie utworzony przez Inkscape na ciąg znaków z tym parkingiem numer miejsca. Inkscape potrzebuje tylko unikalnych identyfikatorów, generuje nieopisowe identyfikatory, ale będzie respektować, a nie zmieniać identyfikatorów utworzonych przez inne oprogramowanie lub ręcznie utworzonych lub zmienionych przez użytkownika.
  • W tabeli przechowuj współrzędne x i y elementu tekstowego każdego miejsca parkingowego.
  • Czy to w Inkscape, czy przez skrypty, zamień cały tekst miejsca parkingowego na ścieżki.
  • W przypadku cyfr 0–9 dołącz do pliku SVG odpowiednią <defs>sekcję określającą informacje o ścieżce dla każdej cyfry.
  • Zapętlić wszystkie <g>miejsca parkingowe i zastąpić je symbolem<use xlink:href="#digit" x=x y=y />
  • Zysk

Mogę przewidzieć pewne komplikacje, z którymi będziesz musiał sobie poradzić, i powodzenia z nimi.

  • Pętla będzie musiała podzielić ciąg miejsc parkingowych z 2 lub więcej cyfr, a odpowiednie odstępy między pierwszą cyfrą a kolejnymi cyframi mogą być trudne; będzie to w dużej mierze zależeć od używanych czcionek.
  • Nie określasz, w jakiej orientacji znajdują się miejsca parkingowe ani czy znajdują się nawet w zakrzywionych konfiguracjach. Ze względu na ręczne przesunięcia x, y dla liczb dwucyfrowych i większych, może być potrzebna dodatkowa logika, aby obliczyć „orientację” miejsca parkingowego i jak prawidłowo rozmieścić różne ścieżki poszczególnych cyfr od pierwszego.

Mam nadzieję że to pomoże. Powodzenia.

botwhytho
źródło