Pred kratkim sem ustvaril vzorec opečne stene kot del mojega #PetitePatterns serije, izziv, kjer ustvarim vzorce ali teksture organskega videza v SVG znotraj 560 bajtov (ali približno velikosti dveh tvitov). Da bi ustrezal tej omejitvi, sem šel skozi pot, ki me je naučila nekaj radikalnih načinov optimizacije vzorcev SVG, tako da vsebujejo čim manj kode, ne da bi to vplivalo na splošno kakovost slike.
Želim vas popeljati skozi postopek in vam pokazati, kako lahko vzamemo vzorec SVG, ki se začne pri 197 bajtih in vse do zgolj 44 bajtov — neverjetno zmanjšanje za 77.7 %!
Vzorec SVG
To je tako imenovani vzorec opeke »tečeča vez«. To je najpogostejši vzorec opeke, ki ste ga zagotovo že videli: vsaka vrsta opek je zamaknjena za polovico dolžine opeke, kar ustvarja ponavljajoč se zamaknjen vzorec. Razporeditev je precej preprosta, izdelava SVG <pattern>
element, ki se popolnoma prilega za njegovo reprodukcijo v kodi.
SVG <pattern>
element uporablja vnaprej določen grafični objekt, ki ga je mogoče posnemati (ali "popločati") v fiksnih intervalih vzdolž vodoravne in navpične osi. V bistvu definiramo pravokoten vzorec ploščic in ta se ponavlja, da se pobarva območje polnila.
Najprej nastavimo dimenzije opeke in razmik med vsako opeko. Zaradi poenostavitve uporabimo čiste, okrogle številke: širina 100
in višino 30
za opeko, in 10
za vodoravne in navpične reže med njimi.
Nato moramo identificirati našo "osnovno" ploščico. In pod besedo "ploščice" govorim o ploščicah z vzorcem in ne o fizičnih ploščicah, ki jih ne smemo zamenjevati z opekami. Uporabimo označeni del zgornje slike kot našo ploščico z vzorcem: dve celi opeki v prvi vrsti in ena cela stisnjena med dvema pol opekama v drugi vrsti. Upoštevajte, kako in kje so vrzeli vključene, ker jih je treba vključiti v ploščico s ponavljajočim se vzorcem.
Pri uporabi <pattern>
, moramo definirati vzorce width
in height
, ki ustrezata širini in višini osnovne ploščice. Da bi dobili dimenzije, potrebujemo malo matematike:
Tile Width = 2(Brick Width) + 2(Gap) = 2(100) + 2(10) = 220
Tile Height = 2(Bright Height) + 2(Gap) = 2(30) + 2(10) = 80
V redu, naša ploščica z vzorcem je 220✕80
. Prav tako moramo nastaviti patternUnits
atribut, kjer je vrednost userSpaceOnUse
v bistvu pomeni slikovne pike. Nazadnje dodajanje an id
na vzorec je potreben, da se lahko nanj sklicujemo, ko z njim slikamo drug element.
<pattern id="p" width="220" height="80" patternUnits="userSpaceOnUse"> <!-- pattern content here -->
</pattern>
Zdaj, ko smo določili dimenzije ploščice, je izziv ustvariti kodo za ploščico na način, ki upodablja grafiko z najmanjšim možnim številom bajtov. To je tisto, kar upamo, da bomo končali na samem koncu:
Začetna oznaka (197 bajtov)
Najenostavnejši in najbolj deklarativen pristop za poustvarjanje tega vzorca, ki mi pride na misel, je risanje petih pravokotnikov. Privzeto je fill
elementa SVG je črna in stroke
je pregleden. To dobro deluje pri optimizaciji vzorcev SVG, saj nam jih ni treba izrecno deklarirati v kodi.
Vsaka vrstica v spodnji kodi definira pravokotnik. The width
in height
so vedno nastavljene in x
in y
položaji so nastavljeni le, če je pravokotnik odmaknjen od 0
položaj.
<rect width="100" height="30"/>
<rect x="110" width="100" height="30"/>
<rect y="40" width="45" height="30"/>
<rect x="55" y="40" width="100" height="30"/>
<rect x="165" y="40" width="55" height="30"/>
Zgornja vrsta ploščice je vsebovala dve opeki polne širine, druga opeka je postavljena na x="110"
omogoča 10
slikovnih pik vrzeli pred opeko. Podobno obstaja 10
slikovnih pik vrzeli po tem, ker se opeka konča pri 210
slikovnih pik (110 + 100 = 210
) na vodoravni osi, čeprav je <pattern>
širina je 220
slikovnih pik. Potrebujemo nekaj dodatnega prostora; drugače bi se druga opeka združila s prvo opeko v sosednji ploščici.
Opeke v drugi (spodnji) vrsti so zamaknjene, tako da vrstica vsebuje dve polovični opeki in eno celo opeko. V tem primeru želimo, da se opeke polovične širine združijo, tako da ni vrzeli na začetku ali koncu, kar jim omogoča neopazno prelivanje z opekami v sosednjih ploščicah z vzorcem. Pri zamiku teh zidakov moramo vključiti tudi polovične vrzeli, torej x
vrednosti so 55
in 165
Oz.
Ponovna uporaba elementa (-43B, skupaj 154B)
Zdi se neučinkovito tako eksplicitno definirati vsako opeko. Ali ne obstaja kakšen način za optimizacijo vzorcev SVG s ponovno uporabo oblik?
Mislim, da ni splošno znano, da ima SVG a <use>
element. Z njim se lahko sklicujete na drug element in ta referenčni element upodobite kjer koli <use>
se uporablja. S tem prihranimo kar nekaj bajtov, ker lahko izpustimo podajanje širin in višin vsake opeke, razen prve.
To je dejalo, <use>
prihaja z majhno ceno. To pomeni, da moramo dodati id
za element, ki ga želimo ponovno uporabiti.
<rect id="b" width="100" height="30"/>
<use href="#b" x="110"/>
<use href="#b" x="-55" y="40"/>
<use href="#b" x="55" y="40"/>
<use href="#b" x="165" y="40"/>
Najkrajši id
možen je en znak, zato sem izbral "b" za opeko. The <use>
element lahko postavite podobno kot <rect>
, S x
in y
atributi kot odmiki. Ker je vsaka opeka zdaj polne širine, ko smo preklopili na <use>
(ne pozabite, da smo izrecno prepolovili opeke v drugi vrsti ploščice z vzorcem), moramo uporabiti negativ x
vrednost v drugi vrstici, nato se prepričajte, da zadnja opeka prehaja iz ploščice za to brezhibno povezavo med opekami. Vendar so ti v redu, saj se vse, kar pade zunaj ploščice z vzorcem, samodejno odreže.
Ali opazite nekaj ponavljajočih se nizov, ki jih je mogoče zapisati učinkoviteje? Delajmo na naslednjih.
Ponovno pisanje na pot (-54B, skupaj 100B)
<path>
je verjetno najmočnejši element v SVG. Z "ukazi" lahko narišete skoraj vsako obliko d
atribut. Na voljo je 20 ukazov, vendar potrebujemo le najpreprostejše za pravokotnike.
Tukaj sem pristal s tem:
<path d="M0 0h100v30h-100z M110 0h100v30h-100 M0 40h45v30h-45z M55 40h100v30h-100z M165 40h55v30h-55z"/>
Vem, super čudne številke in črke! Vsi imajo pomen, seveda. Evo, kaj se dogaja v tem konkretnem primeru:
M{x} {y}
: Premakne se na točko na podlagi koordinat.z
: Zapre trenutni segment.h{x}
: Iz trenutne točke nariše vodoravno črto z dolžinox
v smeri, ki jo določa znakx
. Male črkex
označuje relativno koordinato.v{y}
: Iz trenutne točke nariše navpično črto z dolžinoy
v smeri, ki jo določa znaky
. Male črkey
označuje relativno koordinato.
Ta oznaka je veliko bolj jedrnata kot prejšnja (prelomi vrstic in presledki zamikov so samo za berljivost). In, hej, uspelo nam je izrezati polovico začetne velikosti in prispeli smo do 100 bajtov. Kljub temu se mi nekaj zdi, da bi to lahko bilo manjše ...
Revizija ploščic (-38B, skupno 62B)
Ali naša ploščica z vzorcem nima ponavljajočih se delov? Jasno je, da se v prvi vrsti ponovi cela opeka, kaj pa druga vrsta? Malo težje je videti, a če srednjo opeko prerežemo na pol, postane očitno.
No, srednja opeka ni ravno prepolovljena. Obstaja rahel odmik, ker moramo upoštevati tudi vrzel. Kakorkoli že, pravkar smo našli enostavnejši vzorec osnovne ploščice, kar pomeni manj bajtov! To tudi pomeni, da ga moramo prepoloviti width
od naših <pattern>
element od 220 do 110.
<pattern id="p" width="110" height="80" patternUnits="userSpaceOnUse"> <!-- pattern content here -->
</pattern>
Zdaj pa poglejmo, kako je narisana poenostavljena ploščica <path>
:
<path d="M0 0h100v30h-100z M0 40h45v30h-45z M55 40h55v30h-55z"/>
Velikost je zmanjšana na 62 bajtov, kar je že manj kot tretjina prvotne velikosti! Toda zakaj bi se ustavili tukaj, ko pa lahko storimo še več!
Ukazi za skrajšanje poti (-9B, skupno 53B)
Vredno se je nekoliko poglobiti <path>
ker ponuja več namigov za optimizacijo vzorcev SVG. Ena napačna predstava, ki sem jo imel pri delu <path>
se nanaša na to, kako fill
atribut deluje. Ker sem se v otroštvu veliko igral z MS Paint, sem se naučil, da mora biti vsaka oblika, ki jo želim zapolniti s trdno barvo, zaprta, tj. nima odprtih točk. V nasprotnem primeru bo barva ušla iz oblike in se razlila po vsem.
V SVG pa to ne drži. Naj citiram spec sam:
Operacija polnjenja zapolni odprte podpoti tako, da izvede operacijo polnjenja, kot da bi bil poti dodan dodatni ukaz »closepath« za povezavo zadnje točke podpoti s prvo točko podpoti.
To pomeni, da lahko izpustimo ukaze za zapiranje poti (z
), ker se podpoti štejejo za samodejno zaprte, ko so izpolnjene.
Druga koristna stvar, ki jo je treba vedeti o ukazih poti, je, da so na voljo v različicah z velikimi in malimi črkami. Male črke pomenijo, da so uporabljene relativne koordinate; velike črke pomenijo, da so namesto tega uporabljene absolutne koordinate.
Malo težje je kot to z H
in V
ukaze, ker vključujejo samo eno koordinato. Takole bi opisal ta dva ukaza:
H{x}
: Nariše vodoravno črto od trenutne točke do koordinatex
.V{y}
: Nariše navpično črto od trenutne točke do koordinatey
.
Ko rišemo prvo opeko v ploščici z vzorcem, začnemo od (0,0)
koordinate. Nato narišemo vodoravno črto do (100,0)
in navpična črta do (100,30)
in na koncu narišite vodoravno črto do (0,30)
. Uporabili smo h-100
ukaz v zadnji vrstici, vendar je enakovreden H0
, kar je dva bajta namesto pet. Zamenjamo lahko dva podobna pojava in razrežemo kodo naše <path>
do tega:
<path d="M0 0h100v30H0 M0 40h45v30H0 M55 40h55v30H55"/>
Dodatnih 9 bajtov je odrezanih – koliko manjšega lahko dosežemo?
Premostitev (-5B, skupaj 48B)
Najdaljši ukazi, ki nam stojijo na poti do popolnoma optimiziranega vzorca SVG, so ukazi »premakni na«, ki zavzamejo 4, 5 oziroma 6 bajtov. Ena omejitev, ki jo imamo, je, da:
Podatkovni segment poti (če obstaja) se mora začeti z ukazom »moveto«.
Ampak to je v redu. Prvi je tako ali tako najkrajši. Če zamenjamo vrstice, lahko pridemo do definicije poti, kjer se moramo premikati samo vodoravno ali navpično med opekami. Kaj pa, če bi lahko uporabili h
in v
ukazi tam namesto M
?
Zgornji diagram prikazuje, kako je mogoče tri oblike narisati z eno potjo. Upoštevajte, da izkoriščamo dejstvo, da fill
delovanje samodejno zapre odprti del med (110,0)
in (0,0)
. S to preureditvijo smo pomaknili tudi režo levo od opeke polne širine v drugi vrsti. Tukaj je videti koda, še vedno razdeljena na eno opeko na vrstico:
<path d="M0 0v30h50V0 h10v30h50 v10H10v30h100V0"/>
Zagotovo smo našli absolutno najmanjšo rešitev zdaj, ko smo padli na 48 bajtov, kajne?! No …
Obrezovanje števk (-4B, skupno 44B)
Če ste lahko nekoliko prilagodljivi z dimenzijami, obstaja še en majhen način, s katerim lahko optimiziramo vzorce SVG. Delali smo s širino opeke 100
slikovnih pik, vendar so to trije bajci. Spreminjanje v 90
pomeni en bajt manj, kadar koli ga moramo zapisati. Podobno smo uporabili vrzel v 10
slikovnih pik — če pa ga spremenimo v 8
namesto tega shranimo bajt za vsako od teh pojavitev.
<path d="M0 0v30h45V0 h8v30h45 v8H8v30h90V0"/>
Seveda to pomeni tudi, da moramo ustrezno prilagoditi dimenzije vzorca. Tukaj je končna optimizirana koda vzorca SVG:
<pattern id="p" width="98" height="76" patternUnits="userSpaceOnUse"> <path d="M0 0v30h45V0h8v30h45v8H8v30h90V0"/>
</pattern>
Druga vrstica v zgornjem izrezku - brez vdolbin - je 44 bajtov. Sem smo prišli od 197 bajtov v šestih ponovitvah. To je debela 77.7 % zmanjšanje velikosti!
Sprašujem pa se … ali je to res najmanjša možna velikost? Ali smo preučili vse možne načine za optimizacijo vzorcev SVG?
Vabim vas, da poskusite in dodatno zmanjšate to kodo ali celo eksperimentirate z alternativnimi metodami za optimizacijo vzorcev SVG. Rad bi videl, ali bi lahko našli pravi globalni minimum z modrostjo množice!
Več o ustvarjanju in optimiziranju vzorcev SVG
Če vas zanima več o ustvarjanju in optimiziranju vzorcev SVG, preberite moj članek o tem ustvarjanje vzorcev s filtri SVG. Če pa si želite ogledati galerijo več kot 60 vzorcev, si lahko ogledate Zbirka PetitePatterns CodePen. Nazadnje, vabljeni k ogledu moje vadnice na YouTubu da se boste še bolj poglobili v vzorce SVG.
Optimiziranje vzorcev SVG na njihovo najmanjšo velikost prvotno objavljeno na CSS-triki. Moral bi prejemanje glasila.
- "
- 10
- 100
- 77
- 9
- 98
- O meni
- absolutna
- Račun
- Dodatne
- vsi
- Dovoli
- že
- Še ena
- pristop
- OBMOČJE
- članek
- lastnosti
- Na voljo
- OSI
- Bit
- črna
- izziv
- spremenite
- zaprto
- Koda
- Skupno
- povezava
- Vsebuje
- vsebina
- koordinate
- bi
- Ustvarjanje
- Trenutna
- datum
- globlje
- navzdol
- konča
- ustanovljena
- vse
- Primer
- Razen
- poskus
- končno
- prva
- fit
- Pretok
- je pokazala,
- nadalje
- vrzel
- pridobivanje
- Globalno
- ob
- višina
- pomoč
- tukaj
- Poudarjeno
- Kako
- HTTPS
- identificirati
- slika
- vključujejo
- vključeno
- IT
- sam
- znano
- uhajanje
- UČITE
- naučili
- vzvod
- vrstica
- malo
- Pogledal
- ljubezen
- IZDELA
- Izdelava
- upravlja
- math
- moti
- več
- Najbolj
- premikanje
- MS
- Številka
- številke
- odmik
- Ok
- odprite
- optimizirana
- drugače
- Vzorec
- fizično
- Točka
- pozicioniran
- mogoče
- močan
- precej
- Cena
- Postopek
- zagotavlja
- kakovost
- krog
- tek
- Je dejal
- brezšivne
- Serija
- nastavite
- Oblike
- Podoben
- Enostavno
- SIX
- Velikosti
- So
- Rešitev
- Nekaj
- Vesolje
- Komercialni
- Začetek
- začne
- Podprti
- pogovor
- skozi
- vrh
- pregleden
- vaje
- uporaba
- vrednost
- Poglej
- W3
- Watch
- dobrodošli
- Kaj
- v
- brez
- delo
- deluje
- deluje
- vredno
- youtube