Desenare cu Two.js

Grafica avansată reprezintă o mare parte a web-ului în aceste zile, dar există și câțiva diferiți difuzori în mix. Ați putea folosi panza, desigur; dar SVG și WebGL sunt de asemenea opțiuni. În acest tutorial, vom examina o bibliotecă de desen relativ nouă, two.js, care oferă un API care face același lucru cu toate cele trei randamente. Dacă sunteți gata, hai să verificăm!


Pasul 1 - Configurarea

Primul pas este crearea unui Două instanță și a pus-o pe pagină. Două constructor ia un obiect cu un număr de parametri:

 var 2 = nou Două (fullscreen: true);

În acest caz, folosim ecran complet , ceea ce face ca zona de desen să preia întreaga fereastră a browserului. Dacă vrem ca zona noastră de desen să aibă o dimensiune specifică, am putea folosi lăţime și înălţime proprietăți; acestea ambele iau un număr pentru o valoare pixel. Există și pornire automată parametru; dacă aceasta este setată la true, toate animațiile vor rula imediat când pagina este încărcată.

Există și tip parametru: aceasta decide care redare va fi utilizat. Puteți alege între panza, SVG și WebGl. Nu introduceți doar numele: utilizați o constantă de bibliotecă: fie Two.Types.canvas, Two.Types.svg, sau Two.Types.webgl. Doar pentru a fi clar, two.js va folosi doar SVG; nu face niciun fel de detectare a funcțiilor pentru a vedea ce va suporta browserul. Va trebui să faceți acest lucru pe cont propriu (și cred că este o idee bună: instrumente mici, un lucru bine și toate acestea).

Deci, odată ce avem Două exemplu, ce facem cu ea. În primul rând, veți dori să o adăugați la pagină. Are un adăuga la metodă care ia un element HTML ca parametru, deci lăsați-l setat:

 

Apoi în main.js, începem cu aceasta:

 var el = document.getElementById ("principal"), două = noi Două (fullscreen: true); two.appendTo (el);

Cu toate acestea, suntem gata să tragem câteva forme.


Pasul 2 - Desenarea unor forme de bază

Vom începe cu forme de bază; în timp ce putem crea propriile noastre forme complexe new Two.Polygon, cele mai simple forme pot fi făcute cu câteva metode la îndemână.

Să începem cu cercuri. makeCircle funcția are trei parametri:

 cerc cerc = două cicluri (110, 110, 100); cerc.fill = "# 881111"; two.update ();

Vom revizui din partea de jos, în sus: apelul către two.update actualizările sunt zona de desenare și de fapt redă conținutul. Înapoi la cerc, primii doi parametri sunt coordonatele x și y pentru centrul cercului. Apoi, al treilea parametru este raza cercului. Toate two.make ... funcțiile returnează a Two.Polygon obiect. Pe măsură ce trecem prin acest tutorial, veți vedea câteva proprietăți și metode pe care le puteți utiliza în aceste forme. Iată primul: completati. Așa cum ați putea ghici, setează culoarea de umplere: orice CSS valabil va face.

Rezultatul ar trebui să arate astfel:

Acum, ce zici de dreptunghiuri? two.makeRectangle metoda ia patru parametri. La fel ca cercul, primii doi parametri marchează X și y coordonate pentru centrul dreptunghiului. Apoi, param trei este lăţime iar paramul patru este înălţime a dreptunghiului.

 var rect = 2.makeRectangle (115, 90, 150, 100); rect.fill = "portocaliu"; rect.opacity = 0.25; rect.noStroke (); two.update ();

Din nou, folosim completati proprietate. De asemenea, folosim opacitate proprietate, care acceptă o valoare zecimală între 0 și 1; avem aici opacitate de patruzeci. În cele din urmă, folosim noStroke , care elimină cursa (marginea) de dreptunghi. Iata ce avem:

Ellipsele sunt destul de simple: așa cum ați putea ghici, primii doi parametri stabilesc centrul elipsei. Apoi, avem lățimea și înălțimea:

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

Pentru proprietăți noi: avem accident vascular cerebral, care stabilește culoarea frontierei; pentru a seta lățimea acestei margini, folosim lățimea liniei proprietate. Atunci, amintiți-vă noStroke? noFill metoda este aceeași, cu excepția faptului că elimină culoarea de umplere pentru forma noastră (fără aceasta, formele noastre implicite la o umplere albă).

Desigur, cele mai simple forme sunt liniile.

 linia var = două linii (10, 10, 110, 210); line.linewidth = 10; line.stroke = "rgba (255, 0, 0, 0,5)";

Primii doi parametri sunt X și y pentru un capăt al liniei; al doilea set este pentru celălalt capăt.

Probabil cea mai ciudată formă de creare este curba. two.makeCurve metoda ia cât mai multe seturi de X y parametrii cum doriți - fiecare pereche fiind un punct în care linia se va curba. Apoi, ultimul parametru este un boolean: faceți-l Adevărat dacă forma este deschisă, ceea ce înseamnă că capetele nu se conectează. Dacă doriți ca două.js să deseneze o linie care să lege cele două capete ale curbelor, ar trebui să fie fals.

 var curve = două .makeCurve (110, 100, 120, 50, 140, 150, 160, 50, 180, 150, 190, 100, adevărat); curve.linewidth = 2; curve.scale = 1,75; curve.ro = Math.PI / 2; // curve.noFill ();

Tu stii lățimea liniei, dar ce zici scară? Putem folosi aceasta pentru a ne micsora sau pentru a ne extinde forma; aici, extindem forma cu 175%. Apoi, putem folosi rotație pentru a ne roti forma printr-un număr de radiani; facem 90 de grade, adică radiani de jumătate PI.

În cele din urmă, ați putea crede că, din moment ce ne-am făcut formă deschisă, nu vom obține o umplere; dar asta nu este adevărat. O curbă neînchisă va avea încă o umplutură, așa că folosim noFill pentru a elimina umplutura si a termina cu doar curba.

Ultimul tip de formă este capcanul: este poligonul general. De fapt, e cam la fel ca curba, cu excepția liniilor care merg direct de la punct la punct.

 var poli = două mărimiPolygon (110, 100, 120, 50, 140, 150, 160, 50, 180, 150, 190, 100); poly.linewidth = 4; transl. polimer = noul doi vector (60, 60); poly.stroke = "#cccccc"; poly.fill = "#ececec";

Ca și în cazul curbei, avem cât mai multe perechi de coordonate pe care le-am dori și apoi booleanul deschis; aici ne îndreptăm fals, astfel încât forma va fi închisă.

De asemenea, setăm o traducere aici; acest lucru ne permite să mutați forma stânga sau dreapta și în sus sau în jos. Am setat traducere proprietate la Two.Vector instanță. Two.Vector constructorul are doi parametri: an X și a y. Acestea ajung să fie coordonatele pentru centrul formei. Nu trebuie să creați un vector nou pentru acest lucru; puteți atribui doar X și y lista de valori:

 transl. x = 60; polotranslation.y = 60;

Iată ce obținem:


Pasul 3 - Efectuarea de grupuri

Până acum, am lucrat cu obiecte de formă individuale; totuși, este posibil să grupeze forme și să interacționeze cu ele ca o singură bucată.

Puteți face un grup cu two.makeGroup metodă. Apoi, îl putem folosi adăuga pentru a adăuga o formă grupului.

 grupul var = două.makeGroup (), rect = 2.makeRectangle (0, 0, 100, 100), circ = două.makeCircul (50, 50, 50);

rect.fill = "roșu"; circ.fill = "albastru"; group.add (RECT); group.add (Circ); two.update ();

Dacă executați acest lucru, este destul de simplu; la fel cum ai putea obține fără grup biți.

Dar, atunci putem lucra cu grupul, folosind oricare dintre transformările pe care le putem face într-o formă individuală. De exemplu, ce zici de o traducere?

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

Ca și în cazul formelor obișnuite, grupurile sunt ordonate de la spate la început în momentul în care sunt create. Cu toate acestea, dacă adăugați o formă unui grup și apoi unui alt grup, acesta va fi eliminat din primul grup. Acest lucru este minunat dacă trebuie să modificați ordinea din față a formei când animați (la care ajungem). Deci, dacă începem cu asta:

 var topGroup = 2.makeGroup (), bottomGroup = 2.makeGroup (), rect = 2.makeRectangle (100, 100, 100, 100), circ = 2.makeCircul (150, 150, 50); rect.fill = "roșu"; circ.fill = "albastru"; topGroup.add (RECT); topGroup.add (Circ); two.update ();

Avem același lucru ca mai sus:

Dar, dacă adăugăm RECT la bottomGroup in schimb…

 bottomGroup.add (RECT);

Acum, pătratul nostru este pe partea de sus.

Pasul 4 - Forme de animație

În cele din urmă, hai să vorbim despre animație. Știți deja că două.js redau formele pe care le-ați creat atunci când sunați two.update (). Dacă sunați two.play () În schimb, e ca și cum ai sunat Actualizați() în mod repetat, folosind Frame Animation Request. De fiecare dată când se întâmplă acest lucru, two.js declanșează un eveniment de "actualizare". Acesta este modul în care putem produce animație: ascultați pentru evenimentul "actualizare"; și când se întâmplă, executați o funcție pentru a configura următorul cadru.

Exemplele noastre de până acum au fost mai degrabă simple, așa că haideți să facem o treabă: Vom crea o planetă în orbită cu propria Lună în orbită. Rețineți că începem prin crearea a două instanțe:

 var el = document.getElementById ("principal"), două = noi Două (fullscreen: true) appendTo (el);

Apoi, trebuie să setăm câteva variabile.

 var EarthAngle = 0, moonAngle = 0, distanta = 30, raza = 50, padding = 100, orbita = 200, offset = orbita + padding, orbits = two.makeGroup ();

Vom crește earthAngle și moonAngle pentru a ajunge planeta noastră și luna în jurul lor orbite. distanţă variabilă este cât de departe va fi luna noastră de pe pământul nostru. rază este raduisul planetei noastre pământ, și umplutură este cât spațiu va avea planeta noastră în afara orbitei sale. Orbita menționată provine din orbită variabil. ofset variabilă este cât de departe planeta noastră va fi compensată de la marginea pânzei. În cele din urmă, orbitele grupul va ține cele două cercuri orbitale, ceea ce ne va permite să le arătăm sau să le ascundem la nevoie. Nu vă faceți griji dacă sunteți puțin confuz; veți vedea cum funcționează toți împreună într-o secundă.

Vom începe cu linia orbitală a pământului. Desigur, este doar un cerc simplu:

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

Nu este nimic nou aici. Iată ce ar trebui să vedeți:

Apoi, trebuie să creăm o planetă și să o punem pe orbită. În primul rând, avem nevoie de un mijloc de a înțelege unde ar trebui plasat pe orbită planeta; și, desigur, acest lucru trebuie să se schimbe pentru fiecare cadru de animație. Deci, să creăm o funcție care să readucă centrul X și y coordonatele orbitei bazate pe unghiul actual de poziționare în jurul cercului și raza orbitei:

 funcția getPositions (unghi, orbită) return x: Math.cos (unghi * Math.PI / 180) * orbită, y: Math.sin (unghi * Math.PI / 180) * orbit; 

Da, este un pic de trigonometrie, dar nu vă faceți griji prea mult: practic, transformăm un unghi (care este un grad) într-un radian, folosind metodele sinusoidale și cosinus JavaScript, apoi multiplicându-l cu orbită. Acum, putem folosi această funcție pentru a adăuga pământul în imagine:

 var pos = getPositions (earthAngle ++, orbita), pământ = 2.m.Ciclul (pos.x + offset, pos.y + offset, radius); earth.stroke = "# 123456"; earth.linewidth = 4; earth.fill = "# 194878";

Începem prin a obține poziția pentru prima earthAngle (valoarea 0, amintiți?); atunci ne facem Pământ bazate pe acele poziții (plus offset) și colorați-o. Iată ce sfârșim:

Acum, să animăm această planetă. Codul legat de eveniment vine de fapt direct din Backbone, astfel încât ar putea să pară familiar:

 two.bind ("actualizare", funcție (frameCount) var pos = getPositions (earthAngle ++, orbită), earth.translation.x = pos.x + offset; two.play ();

Ce se întâmplă aici este că de fiecare dată Actualizați evenimentul apare, folosim getPositions funcție pentru a calcula poziția pentru unghiul următor de pe pământ. Apoi, trebuie doar să setăm centrul pământului în acele noi poziții, plus offsetul. În cele din urmă, sunăm two.play () pentru a începe evenimentele de actualizare. Dacă reîncărcați pagina acum, ar trebui să vedeți că pământul se rotește în jurul orbitei.

Bună treabă până acum, nu? Acum, cum rămâne cu luna și cu orbita sa; acest lucru va merge mai sus lega afirmație.

 var moonOrbit = 2.makeCircle (earth.translation.x, earth.translation.y, raza + distanta); moonOrbit.noFill (); moonOrbit.linewidth = 4; moonOrbit.stroke = "#ccc"; orbits.add (moonOrbit); var pos = getPositions (moonAngle, raza + distanta), luna = 2.micCircul (transm. pământ.x + poz., pământ.translația.y + poz.y, raza / 4); moonAngle + = 5; moon.fill = "# 474747";

Acest lucru arată foarte mult ca și codul pentru planetă: centrăm cercul orbitei Lunii în centrul pământului, cu ajutorul lui traducere proprietăți; raza sa este raza pământului plus distanța pe care luna trebuie să o îndepărteze de pământ. Din nou, adăugăm moonOrbit la orbitele grup.

Apoi, creăm luna, primind mai întâi poziția dorită și creând un cerc în acea locație. Pentru o rază, vom folosi un sfert din raza pe care am folosit-o pentru pământ. Vom imbunatati unghiul lunii cu 5 de fiecare data, asa ca se va misca mai repede decat pamantul.

Se dezactivează animația (comentând two.bind declarație), obținem acest lucru:

Ultimul pas: animați luna. În interiorul aceluiași two.bind declarație, adăugați următoarele rânduri:

 var moonPos = getPositions (moonAngle, raza + distanta); 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;

La fel ca și până acum, obținem noua poziție pentru Lună și o poziționăm relativ la pământ. Apoi, mutăm și inelul orbitor al lunii, astfel încât să rămână centrat pe pământ.

Cu toate acestea, exemplul nostru este complet: Iată o fotografie a acțiunii:

Cum am spus, putem ascunde și orbitele. Deoarece ambii sunt în orbitele grup, putem folosi vizibil proprietatea grupului:

 orbits.visible = false;

Si acum:


Concluzie

Ei bine, asta e o înfășurare pe acest tutorial. Credeți că veți folosi două.js în oricare dintre proiectele proprii? Sau poate aveți o alternativă mai bună? Să auzim despre asta în comentariile!

Cod