Opret en SVG-datavisualisering med PHP

En god programmør er en doven programmør. I en voksende verden af ​​datavisualiseringer skaleres ikke håndværk hvert design. Jeg ville se, om der var en måde at skabe aspekter af visualiseringer ved hjælp af et program, for at gøre output let at skabe og genanvendeligt. Ligesom UNIX-filosofien om løst tilsluttede programmer, var det muligt at opbygge en lille værktøjskasse med løst sammenføjede scripts, der skabte byggesten til visualiseringer?

Der synes ikke at være et accepteret udtryk for dette. Jeg har hørt sætningerne 'deterministisk design', 'programmatisk design' og 'beregningsdesign'. Hvad de alle sigter mod er evnen til konsekvent at oprette et eller andet grafisk element baseret på datainput.

hvordan man tegner en løve, der sidder ned

Vi ser det hele tiden i den virkelige verden. De gamle kviksølvtermometre tog data fra miljøet, temperaturen og konverterede det til en visualisering ved at flytte kviksølv op i pipetten. Hvad er det digitale ækvivalent?

Der er et par kandidatteknologier. Hvis du arbejder online, kommer lærred til at tænke på. Det giver dig mulighed for hurtigt og nemt at tegne rastergrafik. Hvis du vil, er der også masser af billedkodebiblioteker, der kan generere GIF'er, JPEG'er og PNG'er efter anmodning. Men hvad hvis dit mål ikke altid er online? Hvad hvis du sigter mod udskrivning? Derefter kunne du bruge en rastergrafik, men den skulle være temmelig stor. En bedre løsning er at oprette et vektorbaseret billedformat ud fra din kode. Det er her SVG (skalerbar vektorgrafik) træder ind.



Hvad er SVG?

SVG er den lille teknologi, der kunne! Det er over 10 år gammelt, og specifikationen forbedres stadig. SVG blev designet og redesignet med et XML-web i tankerne. SVG Tiny var sat til at tage den mobile verden med storm, men det gjorde det aldrig. Internettet ville have zoombar grafik, der kunne skaleres med dit responsive webdesign, men kun få browsere understøtter SVG. Når man ser sig omkring, skulle man tro, at SVG mislykkedes og er en afskrivning. Internets tab er en programmørs gevinst!

SVG er et XML-baseret sprog, der bruges til at beskrive vektorgrafik. Der er en håndfuld primitiver, som du har brug for at kende, som linje, cirkel, rektangel og sti. Fra disse kan du opbygge meget mere komplekse billeder. Da XML kun er tekst, kan du skrive en SVG-fil i enhver teksteditor. Selv enkle programmeringsscripts kan hurtigt output SVG. Da formatet er tekst, er det muligt at komme ind og tilpasse det, selv efter at din kode er færdig ... Hvis du ikke kan lide farven, skal du åbne Notesblok og finde og udskifte den.

SVG er en smukt enkel ting at lære. I mange år kom jeg aldrig ind i programmering af grafik, fordi du havde brug for at vide om billedformater, og det var som et fremmed sprog, men med SVG er det bare tekst. Internettet vandt, fordi du kunne 'Se kilde'; SVG er et fantastisk billedformat, fordi du kan gøre det samme!



Brug af kode til at opbygge SVG

Opbygning af SVG fra kode har sine fordele. Du kan matematisk producere krævende resultater hver gang. Ved hjælp af algoritmer kan du hurtigt fjerne objekter med nøjagtige intervaller. Jeg har set designere forsøge at snappe objekter til linjer eller bruge reglerne til at måle afstande, kun for at zoome ind, kontrollere det, zoome ud og stadig have det fra min sub-millimeter tolerancer. I kode kan alt dette ignoreres. Utroligt komplekse kurver kan forklares væk med et par linjer i en sti, og bedst af alt er det reproducerbart igen og igen. At generere 10.000 tilfældige prikker i et script er en for loop. I hånden ville dette kræve masser af kopiering og indsætning, og så ville det ikke være virkelig tilfældigt. Kodens kraft til hurtigt at generere designs, der enten er for krævende eller for kedelige for designere, er det søde sted.

Jeg går ikke ind for at fjerne design af grafik fra fagfolk, men snarere at lade kode gøre, hvad det gør bedst. En god programmør er en doven programmør. En god designer skal være doven. Det er ikke nødvendigt at oprette 10.000 tilfældige prikker manuelt. Din tid kunne bruges på meget bedre måder.

Opbygning af SVG via kode er den hurtigste måde at få en base, der let kan importeres til mere kompleks vektorsoftware som Adobe Illustrator eller Inkscape. Derfra kan designet formes yderligere, så det passer til hvert unikke projekts behov.

Eksempler

Hvis vi tager et eksempel, vil tingene være meget klarere. Jeg ser fantastiske designs rundt omkring og spekulerer på, hvordan de gjorde det, og hvordan, eller om det kunne gøres i kode. En af mine favoritter er denne plakat til WIRED-magasinets 15-års jubilæum . I sig selv er det en smuk ting at se på, men indtil du forstår det, får du ikke den subtile reference. Hvert af farvehjulene repræsenterer hovedfarverne på de enkelte nummers omslag. Du kan se over tid, hvordan de gik gennem mørke perioder og lyse farvede perioder. Jeg tænkte ved mig selv, hvordan jeg kunne gå rundt med at gøre noget som dette og skrev et simpelt PHP-script, der ville tage et .net-magasinomslag og producere en lignende effekt.



For at fejre sit jubilæum bestilte WIRED Magazine Fernanda Vigas og Martin Wattenberg i 2008 til at skabe en visualisering af sin historie og kultur

For at fejre sit jubilæum bestilte WIRED Magazine Fernanda Vigas og Martin Wattenberg i 2008 til at skabe en visualisering af sin historie og kultur

At lave .net dækker visualiseringer

For de af jer, der ikke er fortrolige med PHP, SVG eller hvordan man ser dem, er det ret nemt. Jeg leder dig gennem koden og viser dig, hvordan du får vist SVG i browseren og i en teksteditor. Hvis du vil bruge dit eget yndlingssprog, bør det ikke være svært at følge med.

Den første ting, vi skal gøre, er at indlæse det JPG-billede, vi vil analysere. I PHP kan du bruge imagegreatefromjpeg () funktion, hvis de korrekte biblioteker er installeret. Dette returnerer et billedhåndtag, så vi kan stille yderligere spørgsmål om grafikken.

Den næste ting, vi skal gøre, er at få højden og bredden af ​​billedet ved hjælp af imagesx () og forestille sig () funktioner.

Vores mål er at slå op på hver pixelfarve i billedet og tælle hyppigheden af ​​hver. Så vi har brug for en slags matrix. I dette tilfælde oprettede jeg et array kaldet $ rgb = array () , som jeg kan lave en ny nøgle til hver farve og øge værdien som en tæller.

Da vi har billedets højde og bredde, kan vi lave to indlejrede til sløjfer. Vi kan nu gå kolonne for kolonne og se på hver x- og y-pixel ved hjælp af billedfarve () fungere. Linjen $ rgb [imagecolorat ($ im, $ i, $ j)] ++; har adgang til rgb-arrayet ved nøglen svarende til pixelværdien og tilføjer en til denne værdi. Når de to for sløjfer er færdige, vil vi have set på hver eneste pixel, hvilket skaber en flot, kompakt række af kun de kendte farver og deres frekvens.

Endelig sorterer vi denne matrix med asort () så de mest populære farver er i slutningen og de mindste værdier i starten.

Koden i PHP ligner følgende:

På dette tidspunkt er vores $ rgb array fuld; vi har ikke længere brug for kildebilledet, og vi vil oprette en ny visualisering i SVG baseret på dataene.

SVG er XML-baseret, hvilket betyder, at det kun er tekst. Så vi kan simpelthen ekko SVG-kode og se resultaterne. Den første ting, vi skal gøre, fortæller browseren, at dette er SVG snarere end almindelig tekst. I så fald skal vi bruge header() funktion med den passende indholdstype ' billede / svg + xml '. Nu kan browsere eller andre applikationer bruge dette til at gengive det korrekt. Det fungerer muligvis uden dette, men det er bedre at være en god netborger og output dette, hvis du kan.

Derefter udskriver vi XML-erklæringen og SVG DOCTYPE.

Nu kan vi faktisk begynde at komme til SVG-delen, der er specifik for vores image. Ligesom enhver HTML-side har en rod af, har SVG en rod af. Dette tager nogle få parametre, såsom højden og bredden af ​​det endelige billede. Da vi ikke altid ved, hvor stort vores kildebillede vil være, er det lettere at bare lave dette 100% for hver værdi.



Koncentriske ringe stablet for at frembringe effekten

Koncentriske ringe stablet for at frembringe effekten

Logikken til at udgive designet er ret enkel. Vi tager den mindste forekommende farveværdi i billedet og laver en cirkel, der er lig med højden gange bredden.

Det virker ikke intuitivt, at den størst mulige cirkel er den mindst mulige værdi! Hvad vi gør næste vil hjælpe med at rydde dette op.

bedste skærm til fotoredigering under 500

Denne store cirkel er vores grundlag. Vi lægger dette først ned, og vi stabler yderligere cirkler oven på dette og bliver lidt mindre hver gang. I sidste ende vil det eneste, der er synligt fra vores enorme startcirkel, være en lille skive rundt om kanten.

For at udrette alt dette løber vi gennem $ rgb array, der ekstraherer nøglen, som er farven, og værdien, som er frekvensen. Vi kan gøre dette med foreach ($ rgb som $ k => $ v) . De næste par linjer opdeler RGB-værdien i en $ r, $ g, $ b-værdi klar til konvertering til hex. I PHP har du dechex () funktion, som tager et decimaltal og opretter en hexækvivalent. Vi er også nødt til at blokere strengen med ledende nuller, hvis farveværdien er mindre end 16. Hvis vi sætter dem helt, får vi $ hex værdi.

Indtil dette tidspunkt har vi ikke engang udsendt noget SVG-grafisk element. Dette vil være vores første, en cirkel. I SVG til at oprette en cirkel bruger du element med nogle attributter. Disse attributter beskriver både cirklen og dens position. Attributterne cx og cy er cirkelens centrum på x, y-gitteret. Attributten r er radius og udfyldning er en hexadecimeret farve, som cirklen skal udfyldes med. At lave grafiske elementer kunne ikke være meget lettere.

Nu skal vi tage det, vi har lært, og anvende det på vores udvalg af farver. Der er to variabler, som vi skal holde styr på: cirkelens maksimale størrelse og størrelsen på den foregående cirkel. Også for at sikre, at ting ikke kommer ud af hånden, har jeg tilføjet en $ scaler variabel for at forhindre, at størrelsen eksploderer for stor.

Variablen $ c er den maksimale størrelse, som vi konstant reducerer radius fra. Siden $ c er bredden gange højden, hver pixel i den originale grafik er repræsenteret i cirkelens radius. Den næste variabel $ tidligere er størrelsen på den forrige cirkel, vi tegnede. På den måde kan vi langsomt reducere størrelsen på radius baseret på antallet af pixels, vi allerede har lavet cirkler til.

$v){ if($v > 0) { $r = ($k >> 16) & 0xFF; $g = ($k >> 8) & 0xFF; $b = $k & 0xFF; $hex = str_pad(dechex($r),2,'0',STR_PAD_LEFT).str_pad(dechex($g),2,'0',STR_PAD_LEFT).str_pad(dechex($b),2,'0',STR_PAD_LEFT); echo ''; echo ' '; $prev += (int)($v/$scaler); }}echo '';?>

Nærbilleder af ringene uden at kombinere lignende farver

Nærbilleder af ringene uden at kombinere lignende farver

Hvis vi ser på nogle eksempler på output, vil vi hurtigt se, at hver lille skygge i hver farve får sin egen ring. Dette betyder, at anti-aliaset tekst skaber masser af gråtoner, som vi skal kollapse i en enkelt repræsentativ farve. Dette reducerer antallet af ringe, men samtidig er det tydeligere, hvilke farver der skiller sig mest ud. Vi kunne simpelthen tage de fem mest populære farver, men hvad der normalt sker er, at du får lignende nuancer af samme farve i stedet for at repræsentere hele spektret. En bedre måde er at prøve at promovere farver med lignende værdier til den mest populære nabo. For at gøre dette skal vi skrive en simpel funktion, som vi indsætter før SVG-output.

hvordan man optager en handling i Photoshop CC
$rgb = reduceColors($rgb);

Passerer på listen over $ rgb farver får vi deres værdi og frekvens. Ideen er at gennemgå denne fulde liste og oprette en ny liste med de reducerede farver. Jeg har valgt et plus- eller minusområde på 75. Det betyder, at en RGB-værdi på 100.100.100 bliver promoveret til den mest populære farve, hvilket er alt fra 25,25,25 til 175,175,175. Du kan justere denne værdi til at være mere tilgivende eller mere streng. Afhængigt af dine værdier ender du med mere eller mindre ringe.

Først skal vi omvendt sortere arrayet, så de mest populære farver er først. Dette betyder, at vi promoverer til det mest populære snarere end det mindste. Når vi løber gennem $ rgb array, vi har også brug for en sub-loop gennem $ temp array. Hvis dette er en ny farve, vi ikke har set før, sætter vi den i den nye $ temp array. Ellers kan vi føje det til det første, når vi løber igennem $ rgb værdi, som vi finder matchende vores plus / minus interval. I slutningen bruger vi arrayet, så det mindste er først, og returnerer det tilbage, så vi kan output SVG.

function reduceColors($rgb){ $plusminus = 75; arsort($rgb); $temp = array(); // do colour merger foreach($list as $k=>$v){ if($v != 0){ $r = ($k >> 16) & 0xFF; $g = ($k >> 8) & 0xFF; $b = $k & 0xFF; $matched = false; foreach($temp as $m=>$n){ if($m != $k){ $rs = ($m >> 16) & 0xFF; $gs = ($m >> 8) & 0xFF; $bs = $m & 0xFF; if ( ($rs = ($r-$plusminus)) && ($gs = ($g-$plusminus)) && ($bs = ($b-$plusminus)) && $matched == false ) { $temp[$m] += $v; $matched = true; } } } if(!($matched)){ $temp[$k] = $v; } } } asort($temp); return $temp;}

I stedet for at bruge funktionen ville en anden mulighed være at bruge den indbyggede funktion imagetruecolortopalette () , der kan tage et maksimalt antal farver til farvepaletten. Dette løser antallet af mulige farver i ringene og reducerer farven for dig. Resultaterne er måske ikke, hvad du har tænkt dig, men det er et lettere alternativ.

.net-dækninger og ringen, der er fremstillet af koden, der repræsenterer farvemængderne

.net-dækninger og ringen, der er fremstillet af koden, der repræsenterer farvemængderne

Forbedringer

Der er mange måder, dette kan forbedres på. En bedre farveklyngealgoritme, nogle optimerede looping, måske vende den op, så de mest populære farver er på den ydre ring i stedet for den indre. Dette blev designet som blot en hurtig start i en verden af ​​dynamisk genererede visualiseringer. Herfra skal du tage din kreativitet og se, hvad du kan anvende den på.

SVG er næppe den skræmmende teknologi, som du måske havde tænkt. Da det simpelthen er et tekst-, XML-format, kan du skrive scripts på dit yndlingssprog for hurtigt og nemt at generere output. At køre disse scripts på forskellige data producerede forskellige output, men den underliggende kode forbliver den samme, så du hurtigt og nemt kan prototype nye designs. At kende SVG og hvordan man scripter dens output er et andet værktøj i din værktøjskasse, der er nyttigt i mange aspekter på arbejde og leg.