Tegning med Two.js

Avansert grafikk er en stor del av nettet i disse dager, men det er et par forskjellige renderere i blandingen. Du kan selvfølgelig bruke lerret; men SVG og WebGL er også alternativer. I denne opplæringen vurderer vi et relativt nytt tegnebibliotek, two.js, som gir en API som gjør det samme med alle tre av dem. Hvis du er klar, la oss sjekke det ut!


Trinn 1 - Oppsett

Det første trinnet er å lage en to eksempel og sett den på siden. De To entreprenør tar et objekt med en rekke parametere:

 var to = ny to (fullskjerm: ekte);

I dette tilfellet bruker vi full skjerm alternativet, som gjør tegneområdet ta opp hele nettleservinduet. Hvis vi ønsket at tegneområdet skulle ha en bestemt størrelse, kunne vi bruke bredde og høyde egenskaper i stedet; disse begge tar et tall for en pikselverdi. Det er også Auto Start parameter; hvis dette er satt til sant, vil noen animasjoner løpe med en gang når siden er lastet inn.

Det er også type parameter: dette bestemmer hvilken renderer som skal brukes. Du kan velge mellom lerret, SVG og WebGl. Du skriver ikke bare navnet, men: du bruker et bibliotek konstant av forskjellige typer: heller Two.Types.canvas, Two.Types.svg, eller Two.Types.webgl. Bare for å være klar, to.js vil bare standard til å bruke SVG; det gjør ikke noen form for gjenkjenning av funksjoner for å se hva nettleseren vil støtte. Du må gjøre det på egen hånd (og jeg synes det er en god ide: små verktøy, en ting bra og alt det).

Så, når vi har en To eksempel, hva gjør vi med det. Først vil du legge til den på siden. Den har en appendTo metode som tar et HTML-element som en paramter, så la oss sette opp dette:

 

Så, i main.js, vi starter med dette:

 var el = document.getElementById ("main"), to = nye to (fullskjerm: true); two.appendTo (el);

Med alt dette satt opp, er vi klare til å faktisk tegne noen få former.


Trinn 2 - Tegning grunnleggende former

Vi begynner med grunnleggende former; mens vi kan lage våre egne komplekse former med ny to.Polygon, De fleste enkle former kan gjøres med noen få praktiske metoder.

La oss starte med sirkler. De makeCircle funksjonen tar tre parametere:

 varcirkel = two.makeCircle (110, 110, 100); circle.fill = "# 881111"; two.update ();

Vi vurderer fra bunnen, opp: anropet til two.update oppdateringer er tegneområde og gjør faktisk innholdet. Ved å sikkerhetskopiere til sirkelen, er de to første parametrene x- og y-koordinatene for senterets senter. Deretter er den tredje parameteren radius for sirkelen. Alle two.make ... funksjoner returnere a Two.Polygon gjenstand. Når vi går gjennom denne opplæringen, ser du flere egenskaper og metoder som du kan bruke på disse figurene. Her er den første: fylle. Som du kanskje gjetter, setter den fyllfarge: En gyldig CSS vil gjøre.

Resultatet skal se slik ut:

Nå, hva med rektangler? De two.makeRectangle Metoden tar fire parametere. På samme måte som sirkelen, markerer de to første parameterne x og y koordinater for midtpunktet av rektangelet. Så er param tre bredde og param fire er høyde av rektangelet.

 var rekt = two.makeRectangle (115, 90, 150, 100); rect.fill = "orange"; rekt.opacitet = 0,25; rect.noStroke (); two.update ();

Igjen bruker vi fylle eiendom. Vi bruker også opasitet eiendom, som aksepterer en desimalverdi mellom 0 og 1; vi har en kvart-opacity her. Til slutt bruker vi noStroke metode, som fjerner streken (grensen) fra rektangelet. Her er hva vi har:

Ellipsene er ganske enkle også: Som du kanskje gjetter, setter de to første parametrene midtpunktet av ellipsen. Da har vi bredde og høyde:

 var ellipse = two.makeEllipse (100, 40, 90, 30); ellipse.stroke = "# 112233"; ellipse.linewidth = 5; ellipse.noFill (); two.update ();

For nye eiendommer: vi har hjerneslag, som setter fargen på grensen; For å sette bredden på den grensen bruker vi linje bredde eiendom. Husk da noStroke? De noFill Metoden er den samme, unntatt fjerner fyllfarge for vår form (uten det, våre figurer er standard til en hvit fylling).

Selvfølgelig er de enkleste formene linjer.

 var linje = two.makeLine (10, 10, 110, 210); line.linewidth = 10; line.stroke = "rgba (255, 0, 0, 0,5)";

De to første parameterne er x og y for den ene enden av linjen; Det andre settet er for den andre enden.

Sannsynligvis er den vanskeligste formen å skape kurven. De two.makeCurve Metoden tar så mange sett av x, y parametre som du vil - hvert par er et punkt der linjen vil kurve. Da er den siste parameteren en boolsk: gjør det ekte Hvis formen er åpen, betyr endene ikke tilkobling. Hvis du vil ha two.js for å tegne en linje som forbinder de to ender av kurvene, bør det være falsk.

 var kurve = two.makeCurve (110, 100, 120, 50, 140, 150, 160, 50, 180, 150, 190, 100, sant); kurve.linewidth = 2; kurve.skala = 1,75; kurve.rotasjon = Math.PI / 2; // Quarter-turn curve.noFill ();

Du vet linje bredde, men hva med skala? Vi kan bruke dette til å krympe eller utvide vår form; her utvider vi formen med 175%. Så kan vi bruke rotasjon å rotere formen vår med en rekke radianer; Vi gjør 90 grader, som er halv-PI-radianer.

Til slutt kan du tenke at siden vi har formet åpen, vil vi ikke få en fylling; men det er ikke sant. En lukket kurve vil fortsatt ha en fylling, så vi bruker noFill å fjerne fyllingen og ende opp med bare kurven.

Den siste formetypen er fangst-all: det er den generelle polygonen. Egentlig er det ganske mye akkurat som kurven, bortsett fra at linjene går rett fra punkt til punkt.

 var poly = two.makePolygon (110, 100, 120, 50, 140, 150, 160, 50, 180, 150, 190, 100); poly.linewidth = 4; poly.translation = ny Two.Vector (60, 60); poly.stroke = "#cccccc"; poly.fill = "#ececec";

Som med kurven har vi så mange par koordinater som vi vil, og deretter den åpne boolske; her setter vi det på falsk, slik at formen lukkes.

Vi setter også inn en oversettelse her; Dette gjør at vi kan flytte formen til venstre eller høyre og opp eller ned. Vi setter inn oversettelse eiendom til a Two.Vector forekomst. De Two.Vector Konstruktøren tar to parametere: an x og a y. Disse ender opp som koordinatene til formens midtpunkt. Du trenger egentlig ikke å lage en ny vektor for dette; du kan bare tildele x og y verdier katalog:

 poly.translation.x = 60; poly.translation.y = 60;

Her er hva vi får:


Trinn 3 - Lag grupper

Så langt har vi jobbet med individuelle formobjekter; Det er imidlertid mulig å gruppere former sammen og samhandle med dem som ett stykke.

Du kan lage en gruppe med two.makeGroup metode. Så kan vi bruke det Legg til Metode for å legge til en form for gruppen.

 var gruppe = two.makeGroup (), rekt = two.makeRectangle (0, 0, 100, 100), sirkel = two.makeCircle (50, 50, 50);

rect.fill = "rød"; circ.fill = "blue"; group.add (rect); group.add (Circ); two.update ();

Hvis du kjører dette, er det ganske grunnleggende; akkurat som du ville få uten gruppe bits.

Men da kan vi jobbe med gruppen ved å bruke noen av de transformasjonene vi kan gjøre på en individuell måte. For eksempel, hva med en oversettelse?

 group.translation.x = 100; group.translation.y = 100; two.update ();

Som med vanlige former bestilles grupper fra baksiden til side når de er opprettet. Men hvis du legger til en form i en gruppe, og deretter en annen gruppe, blir den fjernet fra den første gruppen. Dette er flott hvis du må endre front-to-back rekkefølgen av figurene når du animerer (som vi kommer til). Så, hvis vi starter med dette:

 var topGroup = two.makeGroup (), bottomGroup = two.makeGroup (), rekt = two.makeRectangle (100, 100, 100, 100), sirkel = two.makeCircle (150, 150, 50); rect.fill = "rød"; circ.fill = "blue"; topGroup.add (rect); topGroup.add (Circ); two.update ();

Vi har det samme som ovenfor:

Men hvis vi legger til rect til bottomGroup i stedet…

 bottomGroup.add (rect);

Nå er vårt torg på toppen.

Trinn 4 - Animasjonsformer

Til slutt, la oss snakke om animasjon. Du vet allerede at two.js gjør figurene du har opprettet når du ringer two.update (). Hvis du ringer two.play () I stedet er det som å ringe Oppdater() gjentatte ganger, ved hjelp av Request Animation Frame. Hver gang dette skjer, brenner two.js en "oppdatering" -hendelse. Slik kan vi produsere animasjon: lytt etter "oppdatering" hendelsen; og når det skjer, kjør en funksjon for å sette opp neste ramme.

Våre eksempler så langt har vært ganske enkle, så la oss få ting i en hakk: Vi skal skape en banebrytende planet med sin egen banebrytende måne. Husk at vi begynner med å lage to forekomster:

 var el = document.getElementById ("main"), to = nye to (fullscreen: true). appendTo (el);

Deretter må vi sette opp noen få variabler.

 var earthAngle = 0, moonAngle = 0, avstand = 30, radius = 50, polstring = 100, bane = 200, offset = bane + polstring, baner = two.makeGroup ();

Vi øker earthAngle og moonAngle å få vår planet og månen rundt sine baner. De avstand variabel er hvor langt månen vår kommer fra vår jord. De radius er raduis av vår planet jorden, og padding er hvor mye plass vår planet vil ha utenfor sin bane. Den nevnte bane kommer fra bane variabel. De offset variabel er hvor langt planeten vår vil bli kompensert fra kanten av lerretet. Endelig, den baner gruppen vil holde de to bane sirkler, som vil tillate oss å vise eller skjule dem på vilje. Ikke bekymre deg hvis du er litt forvirret; Du vil se hvordan de alle jobber sammen om et sekund.

Vi starter med jordens omløpslinje. Selvfølgelig er det bare en enkel sirkel:

 var earthOrbit = two.makeCircle (offset, offset, bane); earthOrbit.noFill (); earthOrbit.linewidth = 4; earthOrbit.stroke = "#ccc"; orbits.add (earthOrbit); two.update ();

Det er ikke noe nytt her i det hele tatt. Her er hva du bør se:

Da må vi lage en planet og plassere den på sin bane. For det første trenger vi et middel for å finne ut hvor i planen skal planeten plasseres; og selvfølgelig må dette endres for hver animasjonsramme. Så la oss lage en funksjon som kommer tilbake til senteret x og y koordinater for bane basert på nåværende vinkel for posisjonering rundt sirkelen og baneens radius:

 funksjon getPositions (vinkel, bane) return x: Math.cos (vinkel * Math.PI / 180) * bane, y: Math.sin (vinkel * Math.PI / 180) * bane; 

Ja, det er litt trigonometri, men bekymre deg ikke for mye: Vi konverterer i utgangspunktet vinkelen (som er en grad) til en radian, ved hjelp av JavaScript-sinus og cosinus-metodene, og deretter multipliserer den med bane. Nå kan vi bruke denne funksjonen til å legge til jorden på bildet:

 var pos = getPositions (earthAngle ++, bane), jord = two.makeCircle (pos.x + offset, pos.y + offset, radius); earth.stroke = "# 123456"; earth.linewidth = 4; earth.fill = "# 194878";

Vi starter med å få stillingen til den første earthAngle (verdi på 0, husk?); da gjør vi vår jord basert på disse stillingene (pluss offset) og fargelegge det. Her er hva vi ender med:

Nå, la oss animere denne planeten. Hendelses bindende koden kommer faktisk rett fra Ryggraden, så det kan se kjent ut:

 two.bind ("update", funksjon (frameCount) var pos = getPositions (earthAngle ++, bane); earth.translation.x = pos.x + offset; earth.translation.y = pos.y + offset;); two.play ();

Det som skjer her er at hver gang Oppdater hendelsen oppstår, bruker vi getPositions funksjon for å beregne posisjonen for neste vinkel på jorden. Da må vi bare sette senteret til jorden til de nye stillingene, pluss offsetet. Til slutt, vi ringer two.play () for å starte oppdateringshendelsene. Hvis du oppdaterer siden nå, bør du se at jorden roterer rundt banen.

Fin jobb så langt, eh? Nå, hva med månen og dens banebane; Dette vil gå over binde uttalelse.

 var moonOrbit = two.makeCircle (earth.translation.x, earth.translation.y, radius + avstand); moonOrbit.noFill (); moonOrbit.linewidth = 4; moonOrbit.stroke = "#ccc"; orbits.add (moonOrbit); var pos = getPositions (moonAngle, radius + avstand), moon = two.makeCircle (earth.translation.x + pos.x, earth.translation.y + pos.y, radius / 4); moonAngle + = 5; moon.fill = "# 474747";

Dette ser mye ut som koden for planeten: vi senterer månens bane-sirkel i midten av jorden ved hjelp av dens oversettelse eiendommer; dens radius er jordens radius og avstanden må månen være vekk fra jorden. Igjen legger vi til moonOrbit til baner gruppe.

Deretter lager vi månen, ved først å få sin ønskede posisjon og lage en sirkel på den plasseringen. For en radius bruker vi kvart av radiusen vi brukte til jorden. Vi vil imcrementing månens vinkel med 5 hver gang, så det vil bevege seg raskere enn jorden.

Slår av animasjonen (ved å kommentere two.bind uttalelse), får vi dette:

Siste skritt: få månen å animere. Innenfor det samme two.bind uttalelse, legg til disse linjene:

 var moonPos = getPositions (moonAngle, radius + distance); moon.translation.x = earth.translation.x + moonPos.x; moon.translation.y = earth.translation.y + moonPos.y; moonAngle + = 5; moonOrbit.translation.x = earth.translation.x; moonOrbit.translation.y = earth.translation.y;

Akkurat som før, får vi den nye posisjonen til månen, og posisjonerer den i forhold til jorden. Deretter beveger vi også månens bane ring slik at den forblir sentrert på jorden.

Med alt dette på plass, er vårt lille eksempel fullført: Her er et stillbilde av handlingen:

Som jeg sa, kan vi også skjule banene. Siden de er begge i baner gruppe, kan vi bruke synlig eiendom i gruppen:

 orbits.visible = false;

Og nå:


Konklusjon

Vel, det er en pakke på denne opplæringen. Tror du at du bruker two.js i noen av dine egne prosjekter? Eller kanskje du har et bedre alternativ? La oss høre om det i kommentarene!