Am creat recent un model de perete de cărămidă ca parte a mea #PetitePatterns serie, o provocare în care creez modele sau texturi cu aspect organic în SVG în 560 de octeți (sau aproximativ dimensiunea a două tweet-uri). Pentru a se potrivi acestei constrângeri, am trecut printr-o călătorie care m-a învățat câteva moduri radicale de optimizare a modelelor SVG, astfel încât să conțină cât mai puțin cod posibil, fără a afecta calitatea generală a imaginii.
Vreau să vă ghidez prin proces și să vă arăt cum putem lua un model SVG care începe de la 197 de octeți până la doar 44 de octeți - o reducere uimitoare de 77.7%!
Modelul SVG
Acesta este ceea ce se numește un model de cărămidă „running bond”. Este cel mai comun model de cărămidă de acolo și unul pe care cu siguranță l-ați mai văzut înainte: fiecare rând de cărămizi este compensat cu jumătate din lungimea unei cărămizi, creând un model eșalonat care se repetă. Aranjamentul este destul de simplu, făcând SVG-uri <pattern>
element perfect pentru a-l reproduce în cod.
SVG-ul <pattern>
elementul folosește un obiect grafic predefinit, care poate fi replicat (sau „tiglat”) la intervale fixe de-a lungul axelor orizontale și verticale. În esență, definim un model de plăci dreptunghiulare și se repetă pentru a picta zona de umplere.
Mai întâi, să setăm dimensiunile unei cărămizi și spațiul dintre fiecare cărămidă. De dragul simplității, să folosim numere curate, rotunde: o lățime de 100
si o inaltime de 30
pentru cărămidă, și 10
pentru golurile orizontale și verticale dintre ele.
În continuare, trebuie să identificăm țigla noastră „de bază”. Și prin „țiglă” vorbesc mai degrabă de plăci cu model decât de plăci fizice, care nu trebuie confundate cu cărămizi. Să folosim partea evidențiată a imaginii de mai sus ca plăci de model: două cărămizi întregi în primul rând și una întreagă plasată între două jumătate de cărămizi pe al doilea rând. Observați cum și unde sunt incluse golurile, deoarece acestea trebuie incluse în țiglă cu model repetat.
Atunci când se utilizează <pattern>
, trebuie să definim modelele width
și height
, care corespund cu lățimea și înălțimea plăcii de bază. Pentru a obține dimensiunile, avem nevoie de puțină matematică:
Tile Width = 2(Brick Width) + 2(Gap) = 2(100) + 2(10) = 220
Tile Height = 2(Bright Height) + 2(Gap) = 2(30) + 2(10) = 80
Bine, așa că plăcile noastre cu model este 220✕80
. De asemenea, trebuie să setăm patternUnits
atribut, unde valoarea userSpaceOnUse
în esență înseamnă pixeli. În cele din urmă, adăugarea unui id
la model este necesar pentru ca acesta să poată fi referit atunci când pictăm un alt element cu el.
<pattern id="p" width="220" height="80" patternUnits="userSpaceOnUse"> <!-- pattern content here -->
</pattern>
Acum că am stabilit dimensiunile plăcilor, provocarea este de a crea codul pentru plăci într-un mod care redă graficul cu cel mai mic număr de octeți posibil. Iată ceea ce sperăm să ajungem la final:
Marcare inițială (197 de octeți)
Cea mai simplă și mai declarativă abordare pentru a recrea acest model care îmi vine în minte este să desenez cinci dreptunghiuri. În mod implicit, fill
a unui element SVG este negru și stroke
este transparent. Acest lucru funcționează bine pentru optimizarea modelelor SVG, deoarece nu trebuie să le declarăm în mod explicit în cod.
Fiecare linie din codul de mai jos definește un dreptunghi. The width
și height
sunt întotdeauna setate, iar x
și y
pozițiile sunt setate numai dacă un dreptunghi este decalat față de 0
poziție.
<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"/>
Rândul de sus al plăcii conținea două cărămizi cu lățime întreagă, a doua cărămidă este poziționată x="110"
permiţând 10
pixeli de gol înainte de cărămidă. La fel, există 10
pixeli de decalaj după, deoarece cărămida se termină la 210
pixeli (110 + 100 = 210
) pe axa orizontală chiar dacă <pattern>
lățimea este 220
pixeli. Avem nevoie de acel puțin spațiu suplimentar; în caz contrar, a doua cărămidă s-ar îmbina cu prima cărămidă din țigla adiacentă.
Cărămizile din al doilea rând (de jos) sunt decalate, astfel încât rândul conține două jumătate de cărămidă și o cărămidă întreagă. În acest caz, dorim ca cărămizile de jumătate de lățime să se îmbine, astfel încât să nu existe un spațiu la început sau la sfârșit, permițându-le să curgă perfect cu cărămizile din plăcile model alăturate. Atunci când compensăm aceste cărămizi, trebuie să includem și jumătate de goluri, astfel încât x
valorile sunt 55
și 165
, respectiv.
Reutilizarea elementelor, (-43B, 154B total)
Pare ineficient să definim fiecare cărămidă atât de explicit. Nu există vreo modalitate de a optimiza modelele SVG prin reutilizarea formelor?
Nu cred că este cunoscut faptul că SVG are un <use>
element. Puteți face referire la un alt element cu acesta și puteți reda acel element referit oriunde <use>
este folosit. Acest lucru economisește destul de mulți octeți, deoarece putem omite specificarea lățimilor și înălțimii fiecărei cărămizi, cu excepția primei.
Acestea fiind spuse, <use>
vine cu un mic pret. Adică trebuie să adăugăm un id
pentru elementul pe care vrem să-l reutilizam.
<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"/>
Cel mai scurt id
posibil este un caracter, așa că am ales „b” pentru cărămidă. The <use>
elementul poate fi poziționat similar cu <rect>
, Cu x
și y
atribute ca decalaje. Deoarece fiecare cărămidă are lățime întreagă acum când am trecut la <use>
(rețineți că am înjumătățit în mod explicit cărămizile din al doilea rând al plăcilor de model), trebuie să folosim un negativ x
valoarea din al doilea rând, apoi asigurați-vă că ultima cărămidă se revarsă din țiglă pentru acea conexiune fără sudură între cărămizi. Acestea sunt în regulă, totuși, pentru că orice se încadrează în afara plăcii de model este tăiat automat.
Puteți observa câteva șiruri care se repetă care pot fi scrise mai eficient? Să lucrăm la acestea în continuare.
Rescriere în cale (-54B, 100B total)
<path>
este probabil cel mai puternic element din SVG. Puteți desena aproape orice formă cu „comenzi” în ea d
atribut. Sunt 20 de comenzi disponibile, dar avem nevoie doar de cele mai simple pentru dreptunghiuri.
Iată unde am aterizat cu asta:
<path d="M0 0h100v30h-100z M110 0h100v30h-100 M0 40h45v30h-45z M55 40h100v30h-100z M165 40h55v30h-55z"/>
Știu, numere și litere super ciudate! Toate au sens, desigur. Iată ce se întâmplă în acest caz specific:
M{x} {y}
: Se deplasează la un punct pe baza coordonatelor.z
: Închide segmentul curent.h{x}
: Desenează o linie orizontală din punctul curent, cu lungimea dex
în direcţia definită de semnul dex
. Litere micix
indică o coordonată relativă.v{y}
: Desenează o linie verticală din punctul curent, cu lungimea dey
în direcţia definită de semnul dey
. Litere miciy
indică o coordonată relativă.
Acest marcaj este mult mai concis decât cel precedent (întrerupțiile de linie și spațiile albe de indentare sunt doar pentru lizibilitate). Și, hei, am reușit să tăiem jumătate din dimensiunea inițială, ajungând la 100 de octeți. Totuși, ceva mă face să simt că acesta ar putea fi mai mic...
Revizuirea plăcilor (-38B, 62B total)
Tigla noastră cu model nu are părți care se repetă? Este clar că în primul rând se repetă o cărămidă întreagă, dar ce zici de al doilea rând? Este puțin mai greu de văzut, dar dacă tăiem cărămida din mijloc în jumătate devine evident.
Ei bine, cărămida din mijloc nu este tocmai tăiată în jumătate. Există o ușoară compensare pentru că trebuie să luăm în considerare și decalajul. Oricum, tocmai am găsit un model de plăci de bază mai simplu, ceea ce înseamnă mai puțini octeți! Acest lucru înseamnă, de asemenea, că trebuie să reducem la jumătate width
noastre <pattern>
element de la 220 la 110.
<pattern id="p" width="110" height="80" patternUnits="userSpaceOnUse"> <!-- pattern content here -->
</pattern>
Acum să vedem cum este desenată țigla simplificată <path>
:
<path d="M0 0h100v30h-100z M0 40h45v30h-45z M55 40h55v30h-55z"/>
Dimensiunea este redusă la 62 de octeți, ceea ce este deja mai puțin de o treime din dimensiunea originală! Dar de ce să ne oprim aici când putem face și mai multe!
Scurtarea comenzilor de cale (-9B, 53B în total)
Merită să intri puțin mai adânc în <path>
element deoarece oferă mai multe indicii pentru optimizarea modelelor SVG. O concepție greșită pe care am avut-o când lucram <path>
este cu privire la modul în care fill
atributul funcționează. După ce m-am jucat mult cu MS Paint în copilărie, am învățat că orice formă pe care vreau să o umplu cu o culoare solidă trebuie să fie închisă, adică să nu aibă puncte deschise. În caz contrar, vopseaua se va scurge din formă și se va vărsa peste tot.
În SVG, însă, acest lucru nu este adevărat. Lasă-mă să citez spec în sine:
Operația de umplere umple căi secundare deschise efectuând operația de umplere ca și cum ar fi adăugată o comandă suplimentară „închidere cale” pentru a conecta ultimul punct al căii secundare cu primul punct al căii secundare.
Aceasta înseamnă că putem omite comenzile de închidere a căii (z
), deoarece subtraile sunt considerate automat închise atunci când sunt umplute.
Un alt lucru util de știut despre comenzile de cale este că acestea vin în variații cu litere mari și mici. Literele mici înseamnă că sunt folosite coordonatele relative; literele mari înseamnă că sunt folosite în schimb coordonatele absolute.
Este puțin mai complicat decât atât cu H
și V
comenzi deoarece includ doar o coordonată. Iată cum aș descrie aceste două comenzi:
H{x}
: Desenează o linie orizontală de la punctul curent la coordonatăx
.V{y}
: Desenează o linie verticală de la punctul curent la coordonatăy
.
Când desenăm prima cărămidă din țiglă model, începem de la (0,0)
coordonate. Apoi tragem o linie orizontală către (100,0)
și o linie verticală către (100,30)
și, în final, trageți o linie orizontală către (0,30)
. Noi am folosit h-100
comanda din ultima linie, dar este echivalentul lui H0
, care este doi octeți în loc de cinci. Putem înlocui două apariții similare și putem pară codul nostru <path>
pana la asta:
<path d="M0 0h100v30H0 M0 40h45v30H0 M55 40h55v30H55"/>
Alți 9 octeți tăiați - cât de mai mici putem merge?
Conectare (-5B, 48B total)
Cele mai lungi comenzi care stau în calea unui model SVG complet optimizat sunt comenzile „mutare la” care ocupă 4, 5 și, respectiv, 6 octeți. O constrângere pe care o avem este că:
Un segment de date de cale (dacă există unul) trebuie să înceapă cu o comandă „moveto”.
Dar este în regulă. Primul este cel mai scurt oricum. Dacă schimbăm rândurile, putem veni cu o definiție a căii în care trebuie doar să ne mișcăm orizontal sau vertical între cărămizi. Dacă am putea folosi h
și v
comenzi acolo în loc de M
?
Diagrama de mai sus arată cum cele trei forme pot fi desenate cu o singură cale. Rețineți că valorificăm faptul că fill
funcţionarea închide automat partea deschisă între (110,0)
și (0,0)
. Cu această rearanjare, am mutat și golul la stânga cărămizii cu lățime completă din al doilea rând. Iată cum arată codul, încă împărțit într-o cărămidă pe linie:
<path d="M0 0v30h50V0 h10v30h50 v10H10v30h100V0"/>
Cu siguranță, am găsit cea mai mică soluție absolută acum că am ajuns la 48 de octeți, nu?! Bine…
Tăierea cifrelor (-4B, 44B în total)
Dacă puteți fi puțin flexibil cu dimensiunile, există o altă modalitate prin care putem optimiza modelele SVG. Am lucrat cu o lățime de cărămidă de 100
pixeli, dar sunt trei octeți. Schimbându-l în 90
înseamnă un octet mai puțin ori de câte ori trebuie să-l scriem. În mod similar, am folosit un interval de 10
pixeli — dar dacă îl schimbăm în 8
în schimb, salvăm un octet pentru fiecare dintre aceste apariții.
<path d="M0 0v30h45V0 h8v30h45 v8H8v30h90V0"/>
Desigur, acest lucru înseamnă și că trebuie să ajustam dimensiunile modelului în consecință. Iată codul final al modelului SVG optimizat:
<pattern id="p" width="98" height="76" patternUnits="userSpaceOnUse"> <path d="M0 0v30h45V0h8v30h45v8H8v30h90V0"/>
</pattern>
A doua linie din fragmentul de mai sus - fără a număra indentările - este Bytes 44. Am ajuns aici de la 197 de octeți în șase iterații. Asta e un gros Reducere de dimensiune cu 77.7%.!
Mă întreb totuși... este chiar cea mai mică dimensiune posibilă? Am analizat toate modalitățile posibile de a optimiza modelele SVG?
Vă invit să încercați și să minimizați în continuare acest cod, sau chiar să experimentați cu metode alternative de optimizare a modelelor SVG. Mi-ar plăcea să văd dacă am putea găsi adevăratul minim global cu înțelepciunea mulțimii!
Mai multe despre crearea și optimizarea modelelor SVG
Dacă sunteți interesat să aflați mai multe despre crearea și optimizarea modelelor SVG, citiți articolul meu despre crearea de modele cu filtre SVG. Sau, dacă doriți să verificați o galerie de peste 60 de modele, puteți vizualiza Colecția CodePen PetitePatterns. În cele din urmă, sunteți binevenit să vizionați tutorialele mele pe YouTube pentru a vă ajuta să aprofundați și mai mult modelele SVG.
Optimizarea modelelor SVG la cea mai mică dimensiune publicat inițial pe CSS-trucuri. Tu ar trebui primiți buletinul informativ.
- "
- 10
- 100
- 77
- 9
- 98
- Despre Noi
- Absolut
- Cont
- Suplimentar
- TOATE
- Permiterea
- deja
- O alta
- abordare
- ZONĂ
- articol
- atribute
- disponibil
- AXE
- Pic
- Negru
- contesta
- Schimbare
- închis
- cod
- Comun
- conexiune
- conține
- conţinut
- coordona
- ar putea
- Crearea
- Curent
- de date
- Mai adânc
- jos
- se încheie
- stabilit
- tot
- exemplu
- Cu excepția
- experiment
- În cele din urmă
- First
- potrivi
- debit
- găsit
- mai mult
- decalaj
- obtinerea
- Caritate
- având în
- înălțime
- ajutor
- aici
- Evidențiat
- Cum
- HTTPS
- identifica
- imagine
- include
- inclus
- IT
- în sine
- cunoscut
- scăpa
- AFLAȚI
- învățat
- efectului de pârghie
- Linie
- mic
- uitat
- dragoste
- FACE
- Efectuarea
- gestionate
- matematica
- minte
- mai mult
- cele mai multe
- muta
- MS
- număr
- numere
- compensa
- Bine
- deschide
- optimizate
- in caz contrar
- Model
- fizic
- Punct
- poziţionat
- posibil
- puternic
- destul de
- preţ
- proces
- furnizează
- calitate
- rotund
- funcţionare
- Said
- fără sudură
- serie
- set
- forme
- asemănător
- simplu
- SIX
- Mărimea
- So
- soluţie
- ceva
- Spaţiu
- Loc
- Începe
- începe
- Suportat
- vorbesc
- Prin
- top
- transparent
- tutoriale
- utilizare
- valoare
- Vizualizare
- W3
- Ceas
- bun venit
- Ce
- în
- fără
- Apartamente
- de lucru
- fabrică
- valoare
- youtube