Aan de slag in WebGL, deel 2 het canvaselement voor onze eerste shader

In het vorige artikel schreven we onze eerste vertex en fragment shaders. Als je de GPU-code hebt geschreven, is het tijd om te leren hoe je de CPU-side code schrijft. In deze en de volgende handleiding laat ik u zien hoe u shaders opneemt in uw WebGL-toepassing. We beginnen helemaal opnieuw, alleen met JavaScript en zonder bibliotheken van derden. In dit gedeelte behandelen we de canvasspecifieke code. In de volgende bespreken we de WebGL-specifieke.

Merk op dat deze artikelen:

  • ga ervan uit dat u bekend bent met GLSL-shaders. Zo niet, lees dan het eerste artikel.
  • zijn niet bedoeld om u HTML, CSS of JavaScript te leren. Ik zal proberen de lastige concepten uit te leggen terwijl we ze tegenkomen, maar je zult op het web moeten zoeken naar meer informatie hierover. Het MDN (Mozilla Developer Network) is een uitstekende plaats om dit te doen.

Laten we beginnen!

Wat is WebGL?

WebGL 1.0 is een low-level 3D grafische API voor het web, zichtbaar via het HTML5 Canvas-element. Het is een op shader gebaseerde API die sterk lijkt op de OpenGL ES 2.0 API. WebGL 2.0 is hetzelfde, maar is in plaats daarvan gebaseerd op OpenGL ES 3.0. WebGL 2.0 is niet volledig achterwaarts compatibel met WebGL 1.0, maar de meeste foutloze WebGL 1.0-toepassingen die geen extensies gebruiken, zouden zonder problemen op WebGL 2.0 moeten werken.

Op het moment dat dit artikel werd geschreven, zijn WebGL 2.0-implementaties nog steeds experimenteel in de weinige browsers die het implementeren. Ze zijn ook niet standaard ingeschakeld. Daarom is de code die we in deze reeks schrijven, gericht op WebGL 1.0.

Bekijk het volgende voorbeeld (vergeet niet om van tabblad te veranderen en bekijk ook de code):

Dit is de code die we gaan schrijven. Ja, het duurt iets meer dan honderd regels JavaScript om iets eenvoudigs te implementeren. Maar maak je geen zorgen, we zullen onze tijd nemen om ze uit te leggen, zodat ze allemaal logisch zijn op het einde. We behandelen de canvasgerelateerde code in deze zelfstudie en gaan door naar de WebGL-specifieke code in de volgende.

Het canvas

Eerst moeten we een canvas maken waarin we onze weergegeven dingen kunnen laten zien. 

Dit schattige kleine vierkant is ons canvas! Schakel over naar de HTML bekijken en laten we zien hoe we het hebben gemaakt.

Dit is om de browser te laten weten dat we niet willen dat onze pagina inzoombaar is op mobiele apparaten.

En dit is ons canvaselement. Als we geen dimensies aan ons canvas zouden toewijzen, zou dit standaard 300 * 150 px (CSS-pixels) zijn geweest. Schakel nu over naar CSS bekijken om te controleren hoe we het hebben gestileerd.

canvas ...

Dit is een CSS-selector. Dit specifieke betekent dat de volgende regels worden toegepast op alle canvaselementen in ons document. 

achtergrond: # 0f0;

Eindelijk de regel die moet worden toegepast op de canvaselementen. De achtergrond is ingesteld op felgroen (# 0f0).

Opmerking: in de bovenstaande editor wordt de CSS-tekst automatisch aan het document toegevoegd. Wanneer u uw eigen bestanden maakt, moet u als volgt linken naar het CSS-bestand in uw HTML-bestand:

Zet het bij voorkeur in de hoofd label.

Nu het canvas klaar is, is het tijd om wat spullen te tekenen! Helaas, terwijl het canvas daarboven mooi is, is er nog een lange weg te gaan voordat we iets kunnen tekenen met WebGL. Dus schroot WebGL! Voor deze zelfstudie doen we een eenvoudige 2D-tekening om enkele concepten uit te leggen voordat u overschakelt naar WebGL. Laat onze tekening een diagonale lijn zijn.

Renderende context

De HTML is hetzelfde als het laatste voorbeeld, behalve deze regel:   

waarin we een hebben gegeven ID kaart naar het canvas-element, zodat we het gemakkelijk in JavaScript kunnen terugvinden. De CSS is exact hetzelfde en een nieuw JavaScript-tabblad is toegevoegd om de tekening uit te voeren.

Schakel over naar de JS tab,

window.addEventListener ('load', function () ...);

In het bovenstaande voorbeeld moet de JavaScript-code die we hebben geschreven worden gekoppeld aan de documentkop, wat betekent dat deze wordt uitgevoerd voordat de pagina is geladen. Maar als dat zo is, kunnen we niet naar het canvas trekken, dat nog moet worden gemaakt. Daarom stellen we onze code uit tot nadat de pagina is geladen. Om dit te doen, gebruiken we window.addEventListener, specificeren laden als de gebeurtenis waarnaar we willen luisteren en onze code als een functie die wordt uitgevoerd wanneer de gebeurtenis wordt geactiveerd.

Verder gaan:

var canvas = document.getElementById ("canvas");

Weet je nog de id die we eerder in de HTML aan het canvas hebben toegekend? Hier wordt het nuttig. In de bovenstaande regel halen we het canvaselement uit het document op met zijn ID als referentie. Vanaf nu worden dingen interessanter,

context = canvas.getContext ('2d');

Om elke tekening op het doek te kunnen doen, moeten we eerst een tekencontext aanschaffen. Een context in deze zin is een helperobject dat de vereiste teken-API weergeeft en deze aan het canvaselement koppelt. Dit betekent dat elk volgend gebruik van de API met deze context wordt uitgevoerd op het canvasobject in kwestie.

In dit specifieke geval hebben we een aanvraag ingediend voor een 2d tekencontext (CanvasRenderingContext2D) waarmee we willekeurige 2D-tekenfuncties kunnen gebruiken. We hadden om een ​​kunnen vragen WebGL, een webgl2 of a bitmaprenderer contexten, die elk een andere reeks functies zouden hebben blootgelegd.

Op een canvas is altijd de contextmodus ingesteld geen in eerste instantie. Vervolgens door te bellen getContext, de modus verandert permanent. Het maakt niet uit hoe vaak u belt getContext op een canvas, zal het zijn modus niet veranderen nadat het initieel is ingesteld. Roeping getContext nogmaals, voor dezelfde API wordt hetzelfde contextobject geretourneerd bij het eerste gebruik. Roeping getContext want een andere API zal terugkeren nul.

Helaas kunnen dingen fout gaan. In sommige specifieke gevallen, getContext kan mogelijk geen context maken en zou in plaats daarvan een uitzondering maken. Hoewel dit tegenwoordig vrij zeldzaam is, is het mogelijk met 2d contexten. Dus in plaats van te crashen als dit gebeurt, hebben we onze code ingekapseld in a proberen te vangen blok:

probeer context = canvas.getContext ('2d');  catch (uitzondering) alert ("Umm ... sorry, geen 2d-contexten voor u!" + exceptiebericht); terugkeren; 

Op deze manier kunnen we, als er een uitzondering wordt gegenereerd, het vangen en een foutmelding weergeven, en dan sierlijk gaan om onze hoofden tegen de muur te slaan. Of misschien een statische afbeelding van een diagonale lijn weergeven. Terwijl we dat zouden kunnen doen, tart het het doel van deze tutorial!

Ervan uitgaande dat we met succes een context hebben verkregen, is het enige wat je hoeft te doen de grens trekken:

context.beginPath ();

De 2d context onthoudt het laatste pad dat je hebt geconstrueerd. Het tekenen van een pad verwijdert het niet automatisch uit het geheugen van de context. beginPath vertelt de context om eerdere paden te vergeten en opnieuw te beginnen. Dus ja, in dit geval hadden we deze regel helemaal kunnen weglaten en het zou perfect hebben gewerkt, omdat er geen eerdere paden waren om mee te beginnen.

context.moveTo (0, 0);

Een pad kan uit meerdere subpaden bestaan. moveTo start een nieuw subpad op de vereiste coördinaten.

context.lineTo (30, 30);

Creëert een lijnsegment vanaf het laatste punt op het subpad naar (30, 30). Dit betekent een diagonale lijn van de linkerbovenhoek van het canvas (0, 0) tot de rechterbenedenhoek (30, 30).

context.stroke ();

Een pad maken is één ding; tekenen is een andere. beroerte vertelt de context om alle subpaden in zijn geheugen te tekenen.

beginPath, moveTo, lineTo, en beroerte zijn alleen beschikbaar omdat we om een ​​hebben gevraagd 2d context. Als we bijvoorbeeld een verzoek hebben ingediend WebGL context waren deze functies niet beschikbaar geweest.

Opmerking: in de bovenstaande editor is de JavaScript-code automatisch aan het document gekoppeld. Wanneer u uw eigen bestanden maakt, moet u als volgt naar het JavaScript-bestand in uw HTML-bestand linken:

Je zou het in de hoofd label.

Dit concludeert onze lijntekening tutorial! Maar op de een of andere manier ben ik niet tevreden met dit kleine doek. We kunnen groter dan dit doen!

Canvas formaat

We zullen enkele regels aan onze CSS toevoegen om het canvas de hele pagina te laten vullen. De nieuwe CSS-code ziet er als volgt uit:

html, body height: 100%;  body marge: 0;  canvas weergave: blok; breedte: 100%; hoogte: 100%; achtergrond: # 888; 

Laten we het uit elkaar trekken:

html, body height: 100%; 

De html en lichaam elementen worden behandeld als blokelementen; ze consumeren de volledige beschikbare breedte. Ze breiden echter net genoeg uit om de inhoud in te pakken. Met andere woorden, hun hoogten zijn afhankelijk van de hoogte van hun kinderen. Het instellen van een van de hoogte van hun kinderen tot een percentage van hun lengte zal een afhankelijkheidslus veroorzaken. Dus tenzij we waarden expliciet aan hun hoogten toewijzen, zouden we de onderliggende hoogten niet ten opzichte van hen kunnen instellen.

Omdat we willen dat het canvas de hele pagina vult (stel de hoogte in op 100% van het bovenliggende niveau), stellen we hun hoogte in op 100% (van de paginahoogte).

body marge: 0; 

Browsers hebben standaard stylesheets die een standaardstijl geven aan elk document dat ze renderen. Het heet de user-agent stylesheets. De stijlen in deze bladen zijn afhankelijk van de betreffende browser. Soms kunnen ze zelfs door de gebruiker worden aangepast.

De lichaam element heeft meestal een standaardmarge op de stylesheets van user-agent. We willen dat het canvas de hele pagina vult, dus we stellen de marges in 0.

canvas weergave: blok;

In tegenstelling tot blokelementen zijn inline elementen elementen die als tekst op een reguliere regel kunnen worden behandeld. Ze kunnen elementen voor of na hen op dezelfde regel hebben en ze hebben een lege ruimte eronder waarvan de grootte afhangt van het lettertype en de lettergrootte die in gebruik is. We willen geen lege ruimte onder ons canvas, dus we hebben gewoon zijn weergavemodus ingesteld op blok.

breedte: 100%; hoogte: 100%;

Zoals gepland, stellen we de canvasafmetingen in op 100% van de paginabreedte en -hoogte.

achtergrond: # 888;

Dat hebben we al eerder uitgelegd, nietwaar?!

Zie het resultaat van onze veranderingen ...

...

...

Nee, we hebben niets verkeerd gedaan! Dit is volkomen normaal gedrag. Onthoud de dimensies die we in het canvas aan het canvas gaven HTML label?

Nu zijn we weg en hebben we het canvas andere dimensies in de CSS gegeven:

canvas ... breedte: 100%; hoogte: 100%; ... 

Blijkt dat de dimensies die we in de HTML-tag hebben ingesteld, de intrinsieke dimensies van het canvas. Het canvas is min of meer een bitmap-container. De bitmapafmetingen zijn onafhankelijk van de manier waarop het canvas wordt weergegeven in de uiteindelijke positie en afmetingen op de pagina. Wat deze definieert zijn de extrinsieke dimensies, die we instellen in de CSS.

Zoals we kunnen zien, is onze kleine 30 * 30 bitmap uitgerekt om het hele canvas te vullen. Dit wordt beheerd door de CSS object-fit eigenschap, die standaard is ingesteld vullen. Er zijn andere modi die, bijvoorbeeld, clip in plaats van schaal, maar sindsdien vullen zal ons niet in de weg lopen (eigenlijk kan het nuttig zijn), we laten het gewoon gebeuren. Als u van plan bent om Internet Explorer of Edge te ondersteunen, kunt u er sowieso niets aan doen. Op het moment van schrijven van dit artikel ondersteunen ze niet object-fit helemaal niet.

Houd er echter rekening mee dat de manier waarop de browser de inhoud schaalt nog steeds ter discussie staat. De CSS-eigenschap image-rendering werd voorgesteld om dit aan te pakken, maar het is nog steeds experimenteel (als het überhaupt wordt ondersteund) en het schrijft bepaalde schaalalgoritmen niet voor. Niet alleen dat, de browser kan ervoor kiezen om het volledig te verwaarlozen, omdat het slechts een hint is. Dit houdt in dat verschillende browsers voorlopig verschillende schaalalgoritmen gebruiken om uw bitmap te schalen. Sommige van deze hebben echt verschrikkelijke artefacten, dus schaal niet te veel.

Of we tekenen met een 2d context of andere soorten contexten (zoals WebGL), het canvas gedraagt ​​zich bijna hetzelfde. Als we willen dat onze kleine bitmap het volledige canvas vult en we houden niet van uitrekken, dan moeten we de wijzigingen in de canvasgrootte bekijken en de bitmap-dimensies dienovereenkomstig aanpassen. Laten we dat nu doen,

Kijkend naar de wijzigingen die we hebben aangebracht, hebben we deze twee regels aan het JavaScript toegevoegd:

canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight;

Ja, bij gebruik 2d contexten, het instellen van de interne bitmapdimensies op de canvasdimensies is zo eenvoudig! Het canvas breedte en hoogte worden gemonitord en wanneer een van deze wordt geschreven (zelfs als het dezelfde waarde heeft):

  • De huidige bitmap is vernietigd.
  • Een nieuwe met de nieuwe dimensies is gemaakt.
  • De nieuwe bitmap wordt geïnitialiseerd met de standaardwaarde (transparant zwart).
  • Elke bijbehorende context wordt teruggezet naar de oorspronkelijke status en wordt opnieuw geïnitialiseerd met de nieuw opgegeven coördinaatruimteafmetingen.

Merk op dat, om zowel de breedte en hoogte, de bovenstaande stappen worden uitgevoerd tweemaal! Eenmaal bij het veranderen breedte en de andere bij het veranderen hoogte. Nee, er is geen andere manier om het te doen, niet dat ik weet.

We hebben ook onze korte lijn verlengd om de nieuwe diagonaal te worden,

context.lineTo (canvas.width, canvas.hoogte);

in plaats van: 

context.lineTo (30, 30);

Aangezien we de oorspronkelijke 30 * 30-dimensies niet meer gebruiken, zijn ze niet langer nodig in de HTML:

We hadden ze kunnen laten initialiseren tot zeer kleine waarden (zoals 1 * 1) om de overhead van het maken van een bitmap te besparen met behulp van de relatief grote standaardafmetingen (300 * 150), het te initialiseren, het te verwijderen en vervolgens een nieuwe te maken met de juiste grootte die we instellen in JavaScript.

...

bij nader inzien, laten we dat gewoon doen!

Niemand zou ooit het verschil moeten opmerken, maar ik kan de schuld niet verdragen!

CSS-pixel versus fysieke pixel

Ik had graag gezegd dat dat het was, maar dat is het niet! offsetWidth en offsetHeight zijn gespecificeerd in CSS-pixels. 

Hier is de vangst. CSS-pixels zijn niet fysieke pixels. Het zijn dichtheid-onafhankelijke pixels. Afhankelijk van de fysieke pixeldichtheid van uw apparaat (en uw browser), kan een CSS-pixel overeenkomen met een of meer fysieke pixels.

Als je het op een flauwe manier uitlegt, als je een Full-HD 5-inch smartphone hebt, dan offsetWidth*offsetHeight zou 640 * 360 zijn in plaats van 1920 * 1080. Natuurlijk vult het het scherm, maar omdat de interne dimensies zijn ingesteld op 640 * 360, is het resultaat een uitgerekte bitmap die de hoge resolutie van het apparaat niet volledig benut. Om dit op te lossen, houden we rekening met de devicePixelRatio:

var pixelRatio = window.devicePixelRatio? window.devicePixelRatio: 1.0; canvas.width = pixelRatio * canvas.offsetWidth; canvas.height = pixelRatio * canvas.offsetHeight;

devicePixelRatio is de verhouding tussen de CSS-pixel en de fysieke pixel. Met andere woorden, hoeveel fysieke pixels een enkele CSS-pixel vertegenwoordigt.

var pixelRatio = window.devicePixelRatio? window.devicePixelRatio: 1.0;

window.devicePixelRatio wordt goed ondersteund in de meeste moderne browsers, maar voor het geval het niet gedefinieerd is, vallen we terug naar de standaardwaarde van 1.0.

canvas.width = pixelRatio * canvas.offsetWidth; canvas.height = pixelRatio * canvas.offsetHeight;

Door de CSS-dimensies te vermenigvuldigen met de pixelverhouding, zijn we terug bij de fysieke dimensies. Nu is onze interne bitmap precies dezelfde grootte als het canvas en zal er geen uitrekking plaatsvinden.

Als jouw devicePixelRatio is 1 dan zal er geen verschil zijn. Voor elke andere waarde is het verschil echter significant.

Reageren op wijzigingen in grootte

Dat is niet alles wat te maken heeft met het dimensioneren van canvas. Aangezien we onze CSS-dimensies ten opzichte van het paginaformaat hebben opgegeven, hebben wijzigingen in de paginagrootte wel invloed op ons. Als we een desktopbrowser gebruiken, kan de gebruiker het formaat van het venster handmatig aanpassen. Als we op een mobiel apparaat werken, zijn we onderhevig aan oriëntatiewijzigingen. Niet vermelden dat we binnen in een kunnen rennen iframe die zijn grootte willekeurig verandert. Om ervoor te zorgen dat onze interne bitmap altijd op de juiste manier wordt aangepast, moeten we kijken naar wijzigingen in de grootte van de pagina (venster),

We hebben onze code voor het wijzigen van de grootte van de bitmap verplaatst:

// Verkrijg de pixelverhouding van het apparaat, var pixelRatio = window.devicePixelRatio? window.devicePixelRatio: 1.0; // Pas de canvasgrootte aan, canvas.width = pixelRatio * canvas.offsetWidth; canvas.height = pixelRatio * canvas.offsetHeight;

Naar een afzonderlijke functie, adjustCanvasBitmapSize:

function adjustCanvasBitmapSize () // Verkrijg de pixelverhouding van het apparaat, var pixelRatio = window.devicePixelRatio? window.devicePixelRatio: 1.0; if ((canvas.width / pixelRatio)! = canvas.offsetWidth) canvas.width = pixelRatio * canvas.offsetWidth; if ((canvas.height / pixelRatio)! = canvas.offsetHeight) canvas.height = pixelRatio * canvas.offsetHeight; 

met een kleine aanpassing. Omdat we weten hoe duur het toewijzen van waarden aan breedte of hoogte is, zou het onverantwoord zijn om dit onnodig te doen. Nu zijn we alleen gaan zitten breedte en hoogte wanneer ze daadwerkelijk veranderen.

Omdat onze functie toegang heeft tot ons canvas, verklaren we het waar het het kan zien. Aanvankelijk werd het in deze regel verklaard:

var canvas = document.getElementById ("canvas");

Dit maakt het lokaal voor onze anonieme functie. We hadden zojuist het var deel en het zou zijn geworden globaal (of meer specifiek, een eigendom van de globaal object, die toegankelijk is via venster):

canvas = document.getElementById ("canvas");

Ik raad echter ten zeerste af impliciete verklaring. Als u altijd uw variabelen declareert, voorkomt u veel verwarring. Dus in plaats daarvan ga ik het buiten alle functies verklaren:

var canvas; var context;

Dit maakt het ook een eigenschap van het globale object (met een klein verschil dat ons niet echt hindert). Er zijn andere manieren om een ​​globale variabele te maken - bekijk ze in deze StackOverflow-thread. 

Oh, en ik ben gesnapt context daarboven ook! Dit zal later nuttig blijken.

Laten we nu onze functie aan het venster koppelen verkleinen evenement:

window.addEventListener ('resize', adjustCanvasBitmapSize);

Vanaf nu telkens wanneer de venstergrootte wordt gewijzigd, adjustCanvasBitmapSize wordt genoemd. Maar aangezien de gebeurtenis voor de venstergrootte bij het eerste laden niet wordt gegooid, zal onze bitmap nog steeds 1 * 1 zijn. Daarom moeten we bellen adjustCanvasBitmapSize een keer alleen.

adjustCanvasBitmapSize ();

Dit zorgt er vrijwel voor ... behalve dat wanneer je het formaat van het venster wijzigt, de lijn verdwijnt! Probeer het in deze demo.

Gelukkig is dit te verwachten. Weet je nog de stappen die worden uitgevoerd wanneer de grootte van de bitmap wordt gewijzigd? Een daarvan was om het in transparant zwart te initialiseren. Dit is wat hier gebeurde. De bitmap is overschreven met transparant zwart en nu schijnt de canvas groene achtergrond erdoorheen. Dit gebeurt omdat we in het begin slechts één keer onze lijn tekenen. Wanneer de resize-gebeurtenis plaatsvindt, wordt de inhoud gewist en niet opnieuw getekend. Dit oplossen zou eenvoudig moeten zijn. Laten we het verplaatsen van onze lijn naar een aparte functie verplaatsen:

functie drawScene () // Teken onze regel, context.beginPath (); context.moveTo (0, 0); context.lineTo (canvas.width, canvas.hoogte); context.stroke (); 

en noem deze functie van binnenuit adjustCanvasBitmapSize:

// Alles opnieuw tekenen, drawScene ();

Op deze manier wordt onze scène telkens opnieuw getekend adjustCanvasBitmapSize wordt genoemd, zelfs als er geen verandering in dimensies heeft plaatsgevonden. Om dit aan te pakken, voegen we een eenvoudige controle toe:

// Afbreken als niets is gewijzigd, als (((canvas.width / pixelRatio) == canvas.offsetWidth) && ((canvas.height / pixelRatio) == canvas.offsetHeight)) return; 

Bekijk het eindresultaat:

Probeer het hier te veranderen.

Throttling Resize Events

Tot nu toe doen we het geweldig! Toch kan het aanpassen en hertekenen van alles gemakkelijk heel duur worden als je canvas redelijk groot is en / of als de scène gecompliceerd is. Bovendien kan het wijzigen van het venster met de muis het wijzigen van de grootte van de video met hoge snelheid activeren. Dat is waarom we het zullen smoren. In plaats van:

window.addEventListener ('resize', adjustCanvasBitmapSize);

we zullen gebruiken:

window.addEventListener ('resize', function onWindowResize (event) // Wacht totdat de resizing-gebeurtenissen overstromingen vastlopen, if (onWindowResize.timeoutId) window.clearTimeout (onWindowResize.timeoutId); onWindowResize.timeoutId = window.setTimeout (adjustCanvasBitmapSize, 600 ););

Eerste,

window.addEventListener ('resize', function onWindowResize (event) ...);

in plaats van rechtstreeks te bellen adjustCanvasBitmapSize wanneer de verkleinen evenement is ontslagen, we gebruikten een functie expressie om het gewenste gedrag te definiëren. In tegenstelling tot de functie die we eerder voor de laden gebeurtenis, deze functie is a benoemde functie. Door een naam aan de functie toe te kennen, kunt u er eenvoudig naar verwijzen vanuit de functie zelf.

if (onWindowResize.timeoutId) window.clearTimeout (onWindowResize.timeoutId);

Net als bij andere objecten kunnen eigenschappen worden toegevoegd functie objecten. eerste, timeoutId is onbepaald, dus deze verklaring wordt niet uitgevoerd. Wees echter voorzichtig tijdens het gebruik onbepaald en nul in logische uitdrukkingen, omdat ze lastig kunnen zijn. Lees meer over hen in de ECMAScript-taalspecificatie.

Later, timeoutId zal de timeoutID van een adjustCanvasBitmapSize time-out:

onWindowResize.timeoutId = window.setTimeout (adjustCanvasBitmapSize, 600);

Dit vertraagt ​​bellen adjustCanvasBitmapSize gedurende 600 milliseconden nadat het evenement is afgevuurd. Maar het belet niet dat de gebeurtenis afgaat. Als het binnen deze 600 milliseconden niet opnieuw is geactiveerd, dan adjustCanvasBitmapSize wordt uitgevoerd en de bitmap wordt aangepast. Anders, clearTimeout annuleert de geplande adjustCanvasBitmapSize en setTimeout plant nog eens 600 milliseconden in de toekomst. Het resultaat is, zolang de gebruiker nog steeds het formaat van het venster aanpast, adjustCanvasBitmapSize wordt niet genoemd. Wanneer de gebruiker stopt of een tijdje pauzeert, wordt deze gebeld. Ga je gang, probeer het:

Err ... ik bedoel, hier.

Waarom 600 milliseconden? Ik vind het niet te snel en niet te langzaam, maar het werkt vooral goed bij het invoeren / verwijderen van fullscreen-animaties, wat buiten het bestek van deze tutorial valt.

Dit is onze tutorial voor vandaag! We hebben alle canvasspecifieke code besproken die we nodig hebben om ons canvas in te stellen. Volgende keer, als Allah het wil, zullen we de WebGL-specifieke code bedekken en de arcering daadwerkelijk uitvoeren. Tot die tijd bedankt voor het lezen!

Referenties

  • Canvaselement in w3c-editors-concept
  • w3c-versie waarbij het gedrag voor het initialiseren van het canvas daadwerkelijk is gedocumenteerd
  • Canvaselement in wat live specificatie is