Falleg kóða er gleði að skrifa, en erfitt er að deila gleðiinni með öðrum forriturum, svo ekki sé minnst á forritara. Í frítíma mínum í daglegu starfi og fjölskyldu sinni hef ég verið að leika sér með hugmyndinni um forritunarljóð með því að nota strigaþáttinn til að teikna í vafranum. Það eru margvíslegar hugtök þarna úti til að lýsa sjónrænum tilraunum á tölvunni, svo sem dev list, kóða skissu, kynningu og gagnvirkum listum, en að lokum settist ég á forritunarmál til að lýsa þessu ferli. Hugmyndin að baki ljóð er fáður hluti af prosa sem er auðvelt að deila, nákvæm og fagurfræðileg. Það er ekki hálfgerður hugmynd í skissubók, en samhljóða stykki kynnt fyrir áhorfandann fyrir ánægju sína. Ljóð er ekki verkfæri, en er til þess að vekja tilfinningar.
Fyrir eigin ánægju mína hefur ég lesið bækur um stærðfræði, útreikninga, eðlisfræði og líffræði. Ég hef lært mjög fljótt að þegar ég þyrfti að hugsa um það borar fólk nokkuð fljótt. Sjónrænt get ég tekið nokkrar af þessum hugmyndum sem mér finnst heillandi, og fljótt gefa fólki tilfinningu um furða, jafnvel þótt þeir skilji ekki kenninguna á bak við kóðann og hugtökin sem knýja það. Þú þarft ekki að takast á við hvaða harða heimspeki eða stærðfræði til að skrifa forritunarmynd, bara löngun til að sjá eitthvað lifandi og anda á skjánum.
Kóðinn og dæmi sem ég hef sett saman hér að neðan mun sparka upp skilning á því hvernig á að draga úr þessu fljótlegu og mjög ánægjulegu ferli. Ef þú vilt fylgja með kóðanum sem þú getur sækja skrárnar hér.
Helstu bragð þegar í raun er að búa til ljóð er að halda því í ljós og einfalt. Ekki eyða þremur mánuðum til að byggja upp einn mjög flottan kynningu. Búðu til í stað 10 ljóð sem þróa hugmynd. Skrifaðu tilrauna kóða sem er spennandi og ekki vera hrædd við að mistakast.
Fyrir fljótlegt yfirlit er striga í grundvallaratriðum 2d punktamyndar myndþáttur sem býr í DOM sem hægt er að draga á. Teikning er hægt að gera með því að nota annaðhvort 2d samhengi eða WebGL samhengi. Samhengið er JavaScript hluturinn sem þú notar til að fá aðgang að teikningartólunum. JavaScript viðburðir sem eru í boði fyrir striga eru mjög barebones, ólíkt þeim sem eru í boði fyrir SVG. Allir atburðir sem eru kallaðir eru fyrir þáttinn í heild, ekki neitt dregið á striga, rétt eins og venjulegt myndarþáttur. Hér er undirstöðu striga dæmi:
var canvas = document.getElementById('example-canvas');var context = canvas.getContext('2d');//Draw a blue rectanglecontext.fillStyle = '#91C0FF';context.fillRect(100, // x100, // y400, // width200 // height);//Draw some textcontext.fillStyle = '#333';context.font = "18px Helvetica, Arial";context.textAlign = 'center';context.fillText("The wonderful world of canvas", // text300, // x200 // y);
Það er frekar einfalt að byrja. Það eina sem gæti verið svolítið ruglingslegt er að samhengið þarf að stilla með stillingum eins og fillStyle, lineWidth, leturgerð og strokeStyle áður en raunverulegt teikna símtal er notað. Það er auðvelt að gleyma að uppfæra eða endurstilla þessar stillingar og fá óviljandi niðurstöður.
Fyrsta dæmið hljóp aðeins einu sinni og dró kyrrmynd á striga. Það er allt í lagi, en þegar það gerist í alvöru, er það þegar það er uppfært í 60 rammar á sekúndu. Nútíma vafrar hafa innbyggða aðgerðarbeiðninaAnimationFrame sem samstillir sérsniðna teikna kóða til að draga hringrásina í vafranum. Þetta hjálpar hvað varðar skilvirkni og sléttari. Markmið visualization ætti að vera kóða sem hums með 60 rammar á sekúndu.
(A athugasemd um stuðning: Það eru nokkur einföld polyfills í boði ef þú þarft að styðja eldri vafra.)
var canvas = document.getElementById('example-canvas');var context = canvas.getContext('2d');var counter = 0;var rectWidth = 40;var rectHeight = 40;var xMovement;//Place rectangle in the middle of the screenvar y = ( canvas.height / 2 ) - ( rectHeight / 2 );context.fillStyle = '#91C0FF';function draw() {//There are smarter ways to increment time, but this is for demonstration purposescounter++;//Cool math below. More explanation in the text following the code.xMovement = Math.sin(counter / 25) * canvas.width * 0.4 + canvas.width / 2 - rectWidth / 2;//Clear the previous drawing resultscontext.clearRect(0, 0, canvas.width, canvas.height);//Actually draw on the canvascontext.fillRect(xMovement,y,rectWidth,rectHeight);//Request once a new animation frame is available to call this function againrequestAnimationFrame( draw );}draw();
Nú mun ég umrita formúluna mína frá fyrri kóða fordæmi sem meira brotinn útgáfa sem er auðveldara að lesa.
var a = 1 / 25, //Make the oscillation happen a lot slowerx = counter, //Move along the graph a little bit each time draw() is calledb = 0, //No need to adjust the graph up or downc = width * 0.4, //Make the oscillation as wide as a little less than half the canvasd = canvas.width / 2 - rectWidth / 2; //Tweak the position of the rectangle to be centeredxMovement = Math.sin( a * x + b ) * c + d;
Ef þú vilt spila með kóðanum hingað til, myndi ég mæla með að þú bætir einhverjum hreyfingu í y áttina. Reyndu að breyta gildunum í syndaraðgerðinni eða skipta yfir í einhvers annars konar aðgerð til að spila um kring og sjá hvað gerist.
Handan við akstur hreyfingu með stærðfræði, taktu smá stund til að ímynda þér hvað þú getur gert við mismunandi notendatæki til að færa ferningur um síðu. Það eru alls konar möguleikar í vafranum þar á meðal hljóðnemanum, vefmyndavélinni, músinni, lyklaborðinu og gamepadnum. Viðbótarupplýsingar tappi-ekið valkostur er laus við eitthvað eins og Leap Motion eða Kinect. Notkun WebSockets og miðlara sem þú gætir tengt við visualization við heima-innbyggðan vélbúnað. Haltu upp hljóðnema í forritið Web Audio og dregðu pixla með hljóði. Þú getur jafnvel búið til hreyfimyndavél úr vefmyndavél og hræða skóla af raunverulegum fiski (allt í lagi gerði ég síðast í Flash fimm eða svo árum síðan.)
Svo nú þegar þú hefur stóra hugmynd þína, skulum við hoppa aftur inn í fleiri dæmi. Eitt ferningur er leiðinlegt, við skulum halda áfram. Fyrst af, við skulum búa til fermetra virka sem getur gert mikið. Við munum kalla það punkt. Eitt sem hjálpar til við að vinna með hreyfanlegum hlutum er að nota vektorar frekar en aðskilja x og y breytur. Í þessum kóðaprófum hefur ég dregið í three.js Vector2 bekkinn. Það er auðvelt að nota strax með vector.x og vector.y, en það hefur einnig fullt af sérhönnuðum aðferðum til að vinna með þeim. Sjáðu skjölin fyrir dýpra kafa.
Kóðinn í þessu dæmi er svolítið flóknari vegna þess að það er samskipti við hluti, en það verður þess virði. Skoðaðu dæmi kóðann til að sjá nýja Scene mótmæla sem stjórnar grunnatriðum að teikna á striga. Nýr Dot bekknum okkar mun fá að takast á við þennan vettvang til að fá aðgang að öllum breytum eins og striga samhengi sem það mun þurfa.
function Dot( x, y, scene ) {var speed = 0.5;this.color = '#000000';this.size = 10;this.position = new THREE.Vector2(x,y);this.direction = new THREE.Vector2(speed * Math.random() - speed / 2,speed * Math.random() - speed / 2);this.scene = scene;}
Til að byrja með byggirinn fyrir punktinn setur upp stillingar hegðunar síns og setur nokkur breytur til notkunar. Aftur, þetta er að nota three.js vektor bekknum. Þegar þú gengur við 60fps er mikilvægt að frumstilla hlutina þína og ekki búa til nýjar myndir meðan á hreyfimyndum stendur. Þetta borðar inn í minnið þitt og getur gert visualization þína hakkaleg. Athugaðu einnig hvernig punkturinn er sendur afrit af vettvangi með tilvísun. Þetta heldur hlutunum hreinum.
Dot.prototype = {update : function() {...},draw : function() {...}}
Allt restin af kóðanum verður stillt á frumgerð frumpunktsins þannig að hver nýr punktur sem er búinn til hefur aðgang að þessum aðferðum. Ég mun fara virka með því að virka í skýringunni.
update : function( dt ) {this.updatePosition( dt );this.draw( dt );},
Ég er að skilja út teikningarkóðann frá uppfærsluskóðanum mínum. Þetta gerir það miklu auðveldara að viðhalda og klipa hlutinn, líkt og MVC mynstur skilur stjórnina þína og skoða rökfræði. Dt breytu er tímabreytingin í millisekúndum frá síðustu uppfærslu símtali. Nafnið er gott og stutt og kemur frá (ekki vera hrædd) reikna afleiður. Hvað þetta gerir er aðgreina hreyfingu þína úr hraða rammahraða. Þannig færðu ekki NES stíl hægur þegar hlutirnir verða of flóknar. Hreyfingin þín mun sleppa ramma ef það vinnur hart, en það mun vera á sama hraða.
updatePosition : function() {//This is a little trick to create a variable outside of the render loop//It's expensive to allocate memory inside of the loop.//The variable is only accessible to the function below.var moveDistance = new THREE.Vector2();//This is the actual functionreturn function( dt ) {moveDistance.copy( this.direction );moveDistance.multiplyScalar( dt );this.position.add( moveDistance );//Keep the dot on the screenthis.position.x = (this.position.x + this.scene.canvas.width) % this.scene.canvas.width;this.position.y = (this.position.y + this.scene.canvas.height) % this.scene.canvas.height;}}(), //Note that this function is immediately executed and returns a different function
Þessi aðgerð er svolítið skrýtin í uppbyggingu þess, en hagnýt fyrir visualizations. Það er mjög dýrt að úthluta minni í aðgerð. Breytilegt breytistilling er stillt einu sinni og endurnotuð hvenær aðgerðin er kallað.
Þessi vektor er aðeins notuð til að reikna nýja stöðu, en ekki notuð utan aðgerðarinnar. Þetta er fyrsta vektor stærðfræði sem er að nota. Núna er stefnuvigurinn margfaldaður gegn tímafærslunni og síðan bætt við stöðu. Í lokin er lítið modulo aðgerð í gangi til að halda punktinum á skjánum.
draw : function(dt) {//Get a short variable name for conveniencevar ctx = this.scene.context;ctx.beginPath();ctx.fillStyle = this.color;ctx.fillRect(this.position.x, this.position.y, this.size, this.size);}
Að lokum er auðvelt efni. Fáðu afrit af samhenginu frá svæðis mótmæla og taktu síðan rétthyrningur (eða hvað sem þú vilt). Rétthyrningar eru líklega fljótasti hluturinn sem þú getur teiknað á skjánum.
Á þessum tímapunkti bætir ég nýjum punkti með þessu.dot = nýjum punkti (x, y, þetta) í aðalvettvangsframleiðandanum og síðan er ég að bæta við this.dot.update (dt) punktur zoomandi um skjáinn. (Kíkið á kóðann fyrir fullan kóða í samhengi.)
Nú á vettvangi, frekar en að búa til og uppfæra punkt , búa við og uppfæra DotManager . Við munum búa til 5000 punkta til að byrja.
function Scene() {...this.dotManager = new DotManager(5000, this);...};Scene.prototype = {...update : function( dt ) {this.dotManager.update( dt );}...};
Það er svolítið ruglingslegt í einni línu, svo hér er brotið niður eins og syndaraðgerðin frá fyrra.
var a = 1 / 500, //Make the oscillation happen a lot slowerx = this.scene.currTime, //Move along the graph a little bit each time draw() is calledb = this.position.x / this.scene.canvas.width * 4, //No need to adjust the graph up or downc = 20, //Make the oscillation as wide as a little less than half the canvasd = 0; //Tweak the position of the rectangle to be centeredxMovement = Math.sin( a * x + b ) * c + d;
Að fá groovy ...
Eitt lítið klip. Svart / hvítt er lítið drab, svo við skulum bæta við lit.
var hue = this.position.x / this.scene.canvas.width * 360;this.color = Utils.hslToFillStyle(hue, 50, 50, 0.5);
Þessi einfalda hlutur encapsulates rökfræði músaruppfærslna frá afganginum af vettvangi. Það uppfærir aðeins stöðuveituna á músarfærslu. Afgangurinn af hlutunum getur síðan sýnt úr stöðuvef músarinnar ef þær eru sendar tilvísun í hlutinn. Ein ástæða sem ég er að hunsa hér er ef breidd striga er ekki einn við einn með pixla víddum DOM þ.e. svöruðu stærð striga eða hærri pixla þéttleika (retina) striga eða ef striga er ekki staðsett á efst til vinstri. Hnit músarinnar verður að breyta í samræmi við það.
var Scene = function() {...this.mouse = new Mouse( this );...};
Eina sem eftir var fyrir músina var að búa til músarhlutinn innan svæðisins. Nú þegar við höfum mús, skulum við draga punktana við það.
function Dot( x, y, scene ) {...this.attractSpeed = 1000 * Math.random() + 500;this.attractDistance = (150 * Math.random()) + 180;...}
Ég bætti nokkrum stigagildum við punktinn þannig að hver og einn hegðar sér svolítið öðruvísi í uppgerðinni til að gefa það smá raunsæi. Leika með þessum gildum til að fá aðra tilfinningu. Nú á að laða mús aðferð. Það er svolítið lengi með athugasemdunum.
attractMouse : function() {//Again, create some private variables for this methodvar vectorToMouse = new THREE.Vector2(),vectorToMove = new THREE.Vector2();//This is the actual public methodreturn function(dt) {var distanceToMouse, distanceToMove;//Get a vector that represents the x and y distance from the dot to the mouse//Check out the three.js documentation for more information on how these vectors workvectorToMouse.copy( this.scene.mouse.position ).sub( this.position );//Get the distance to the mouse from the vectordistanceToMouse = vectorToMouse.length();//Use the individual scalar values for the dot to adjust the distance movedmoveLength = dt * (this.attractDistance - distanceToMouse) / this.attractSpeed;//Only move the dot if it's being attractedif( moveLength > 0 ) {//Resize the vector to the mouse to the desired move lengthvectorToMove.copy( vectorToMouse ).divideScalar( distanceToMouse ).multiplyScalar( moveLength );//Go ahead and add it to the current position now, rather than in the draw callthis.position.add(vectorToMove);}};}()
Þessi aðferð gæti verið svolítið ruglingslegt ef þú ert ekki upp til dagsetningar á stærðfræðigröfunni þinni. Vigrar geta verið mjög sjónarlegar og geta hjálpað ef þú dregur út einhverjar skrúfur út á pappírsbrúnum pappír. Í venjulegri ensku er þessi aðgerð að ná fjarlægðinni milli músarinnar og punktarins. Það er þá að færa punktinn svolítið nær punktinum miðað við hversu nær það er þegar punkturinn er og hversu lengi er liðinn. Það gerir þetta með því að reikna út fjarlægðina til að hreyfa (eðlilegt skalalarnúmer) og margfalda það síðan með eðlilegum vektor (vektor með lengd 1) punktsins sem vísar til músarinnar. Allt í lagi, þessi síðasta setning var ekki endilega látin ensku en það er byrjunin.