Im vorigen Artikel haben wir unsere ersten Vertex- und Fragment-Shader geschrieben. Nachdem Sie den GPU-seitigen Code geschrieben haben, ist es Zeit zu lernen, wie der CPU-seitige geschrieben wird. In diesem und im nächsten Tutorial zeige ich Ihnen, wie Sie Shader in Ihre WebGL-Anwendung integrieren. Wir fangen bei Null an und verwenden nur JavaScript und keine Bibliotheken von Drittanbietern. In diesem Teil behandeln wir den Canvas-spezifischen Code. Im nächsten werden wir den WebGL-spezifischen Inhalt behandeln.
Beachten Sie, dass diese Artikel:
Lass uns schon anfangen!
WebGL 1.0 ist eine einfache 3D-Grafik-API für das Web, die über das HTML5-Canvas-Element bereitgestellt wird. Es ist eine Shader-basierte API, die der OpenGL ES 2.0-API sehr ähnlich ist. WebGL 2.0 ist dasselbe, basiert jedoch stattdessen auf OpenGL ES 3.0. WebGL 2.0 ist nicht vollständig abwärtskompatibel mit WebGL 1.0, aber die meisten fehlerfreien WebGL 1.0-Anwendungen, die keine Erweiterungen verwenden, sollten unter WebGL 2.0 problemlos funktionieren.
Zum Zeitpunkt der Erstellung dieses Artikels sind WebGL 2.0-Implementierungen noch in den wenigen Browsern experimentell, die ihn implementieren. Sie sind auch standardmäßig nicht aktiviert. Daher ist der Code, den wir in dieser Serie schreiben werden, auf WebGL 1.0 ausgerichtet.
Sehen Sie sich das folgende Beispiel an (denken Sie daran, die Registerkarten zu wechseln, und werfen Sie auch einen Blick auf den Code):
Dies ist der Code, den wir schreiben werden. Ja, es erfordert tatsächlich etwas mehr als hundert Zeilen JavaScript, um etwas so einfaches zu implementieren. Aber machen Sie sich keine Sorgen, wir nehmen uns Zeit, um sie zu erklären, damit sie am Ende alle einen Sinn ergeben. In diesem Lernprogramm werden wir den Canvas-bezogenen Code behandeln und im nächsten mit dem WebGL-spezifischen Code fortfahren.
Zuerst müssen wir eine Leinwand erstellen, auf der wir unser gerendertes Material zeigen.
Dieses niedliche kleine Quadrat ist unsere Leinwand! Wechseln Sie zu HTML
anschauen und mal sehen, wie wir es gemacht haben.
Damit teilen Sie dem Browser mit, dass unsere Seite auf mobilen Geräten nicht zoombar sein soll.
Und das ist unser Leinwandelement. Wenn wir unserer Leinwand keine Bemaßungen zugewiesen hätten, wäre der Standardwert 300 * 150px (CSS-Pixel). Wechseln Sie jetzt zu CSS
Um zu sehen, wie wir es gestaltet haben.
Segeltuch …
Dies ist ein CSS-Selektor. Dies bedeutet, dass die folgenden Regeln auf alle Leinwandelemente in unserem Dokument angewendet werden.
Hintergrund: # 0f0;
Schließlich muss die Regel auf die Elemente der Leinwand angewendet werden. Der Hintergrund ist auf hellgrün eingestellt (# 0f0
).
Hinweis: Im obigen Editor wird der CSS-Text automatisch an das Dokument angehängt. Wenn Sie Ihre eigenen Dateien erstellen, müssen Sie die CSS-Datei in Ihrer HTML-Datei folgendermaßen verknüpfen:
Legen Sie es vorzugsweise in die Kopf
Etikett.
Nun, da die Leinwand fertig ist, ist es Zeit, etwas zu zeichnen! Während die Leinwand dort oben schön und schön aussieht, haben wir leider noch einen langen Weg vor uns, bevor wir mit WebGL etwas zeichnen können. Also Schrott WebGL! In diesem Lernprogramm führen wir eine einfache 2D-Zeichnung aus, um einige Konzepte zu erläutern, bevor Sie zu WebGL wechseln. Unsere Zeichnung sei eine Diagonale.
Der HTML-Code stimmt mit dem letzten Beispiel überein, mit Ausnahme dieser Zeile:
in dem wir ein gegeben haben Ich würde
auf das Canvas-Element, damit wir es leicht in JavaScript abrufen können. Das CSS ist genau das gleiche und eine neue JavaScript-Registerkarte wurde hinzugefügt, um die Zeichnung auszuführen.
Wechseln Sie zu JS
Tab,
window.addEventListener ('load', function () …);
Im obigen Beispiel soll der von uns geschriebene JavaScript-Code an den Dokumentkopf angehängt werden, dh er wird ausgeführt, bevor die Seite vollständig geladen ist. In diesem Fall können wir jedoch nicht auf die noch zu erstellende Leinwand zeichnen. Deshalb verschieben wir den Code erst nach dem Laden der Seite. Dazu verwenden wir window.addEventListener
, spezifizieren Belastung
Als Ereignis möchten wir uns anhören und unseren Code als Funktion, die ausgeführt wird, wenn das Ereignis ausgelöst wird.
Umzug:
var canvas = document.getElementById ("Leinwand");
Erinnern Sie sich an die ID, die wir zuvor im HTML der Leinwand zugewiesen haben? Hier wird es nützlich. In der obigen Zeile rufen wir das Canvas-Element aus dem Dokument ab, wobei seine ID als Referenz verwendet wird. Ab jetzt werden die Dinge interessanter,
context = canvas.getContext ('2d');
Um auf der Leinwand zeichnen zu können, müssen wir zunächst einen Zeichnungskontext erstellen. Ein Kontext in diesem Sinne ist ein Hilfsobjekt, das die erforderliche Zeichnungs-API verfügbar macht und mit dem Zeichenbereichselement verknüpft. Dies bedeutet, dass jede nachfolgende Verwendung der API, die diesen Kontext verwendet, für das betreffende Canvas-Objekt ausgeführt wird.
In diesem speziellen Fall haben wir a 2d
Zeichnungskontext (CanvasRenderingContext2D
), wodurch wir beliebige 2D-Zeichnungsfunktionen verwenden können. Wir hätten eine beantragen können webgl
, ein webgl2
oder ein Bitmaprenderer
stattdessen Kontexte, von denen jeder einen anderen Satz von Funktionen enthüllt hätte.
Der Hintergrundmodus einer Leinwand ist immer auf festgelegt keiner
anfänglich. Dann durch anrufen getContext
, Sein Modus ändert sich permanent. Egal wie oft Sie anrufen getContext
Auf einer Leinwand ändert sich der Modus nach dem Festlegen nicht. Berufung getContext
Für dieselbe API wird das gleiche Kontextobjekt zurückgegeben, das bei der ersten Verwendung zurückgegeben wird. Berufung getContext
für eine andere API wird zurückgegeben Null
.
Leider kann es schief gehen. In bestimmten Fällen, getContext
kann keinen Kontext erstellen und löst stattdessen eine Ausnahme aus. Während dies heutzutage ziemlich selten ist, ist es mit möglich 2d
Kontexte. Anstatt abstürzen, wenn dies passiert, haben wir unseren Code in a eingekapselt Try-Catch
Block:
try context = canvas.getContext ('2d'); catch (exception) alert ("Umm ... Entschuldigung, keine 2d-Kontexte für Sie!" + exception.message); Rückkehr ;
Auf diese Weise können wir, wenn eine Ausnahme ausgelöst wird, diese abfangen, eine Fehlermeldung anzeigen und dann behutsam unseren Kopf gegen die Wand schlagen. Oder zeigen Sie möglicherweise ein statisches Bild einer diagonalen Linie an. Wir könnten das zwar tun, aber es widerspricht dem Ziel dieses Tutorials!
Vorausgesetzt, wir haben erfolgreich einen Kontext erworben, bleibt nur noch die Linie zu zeichnen:
context.beginPath ();
Das 2d
context merkt sich den zuletzt erstellten Pfad. Das Zeichnen eines Pfads löscht ihn nicht automatisch aus dem Speicher des Kontexts. beginPath
weist den Kontext an, alle vorherigen Pfade zu vergessen und neu zu beginnen. Ja, in diesem Fall hätten wir diese Zeile ganz weglassen können, und es hätte einwandfrei funktioniert, da es keine vorherigen Pfade gab.
context.moveTo (0, 0);
Ein Pfad kann aus mehreren Unterpfaden bestehen. ziehen nach
Startet einen neuen Unterpfad an den erforderlichen Koordinaten.
context.lineTo (30, 30);
Erzeugt ein Liniensegment vom letzten Punkt des Unterpfads bis (30, 30)
. Dies bedeutet eine diagonale Linie von der oberen linken Ecke der Leinwand (0, 0) bis zur rechten unteren Ecke (30, 30)..
context.stroke ();
Einen Pfad zu schaffen ist eine Sache; Zeichnen ist ein anderes. Schlaganfall
weist den Kontext an, alle Unterpfade in seinem Speicher zu zeichnen.
beginPath
, ziehen nach
, lineTo
, und Schlaganfall
sind nur verfügbar, weil wir a 2d
Kontext. Wenn wir zum Beispiel einen beantragten webgl
In diesem Kontext wären diese Funktionen nicht verfügbar gewesen.
Hinweis: Im obigen Editor wird der JavaScript-Code automatisch an das Dokument angehängt. Wenn Sie Ihre eigenen Dateien erstellen, müssen Sie auf die JavaScript-Datei in Ihrer HTML-Datei folgendermaßen verweisen:
Sie sollten es in die Kopf
Etikett.
Damit ist unser Line Drawing-Tutorial abgeschlossen! Aber irgendwie bin ich mit dieser winzigen Leinwand nicht zufrieden. Wir können mehr als das tun!
Wir werden unserem CSS einige Regeln hinzufügen, damit die Leinwand die gesamte Seite ausfüllt. Der neue CSS-Code wird folgendermaßen aussehen:
html, Körper Höhe: 100%; body margin: 0; Zeichenfläche Anzeige: Block; Breite: 100%; Höhe: 100%; Hintergrund: # 888;
Nehmen wir es auseinander:
html, Körper Höhe: 100%;
Das html
und Karosserie
Elemente werden wie Blockelemente behandelt. Sie verbrauchen die gesamte verfügbare Breite. Sie dehnen sich jedoch gerade so weit vertikal aus, dass sie ihren Inhalt einwickeln. Mit anderen Worten, ihre Höhe hängt von der Höhe der Kinder ab. Wenn Sie die Höhe einer ihrer Kinder auf einen Prozentsatz ihrer Höhe einstellen, wird eine Abhängigkeitsschleife ausgelöst. Wenn wir ihren Höhen also nicht explizit Werte zuweisen, können wir die Kinderhöhen nicht relativ zu ihnen festlegen.
Da die Leinwand die gesamte Seite ausfüllen soll (die Höhe auf 100% des übergeordneten Elements setzen), setzen wir ihre Höhe auf 100% (der Seitenhöhe)..
body margin: 0;
Browser verfügen über grundlegende Stylesheets, die jedem von ihnen gerenderten Dokument einen Standardstil zuweisen. Es heißt das Benutzer-Agent-Stylesheets. Die Stile in diesen Tabellen hängen von dem jeweiligen Browser ab. Manchmal können sie sogar vom Benutzer eingestellt werden.
Das Karosserie
Das Element hat normalerweise einen Standardrand in den Stylesheets des Benutzeragenten. Wir möchten, dass die Leinwand die gesamte Seite ausfüllt, so dass wir die Ränder auf einstellen 0
.
Leinwand Anzeige: Block;
Im Gegensatz zu Blockelementen sind Inline-Elemente Elemente, die wie Text in einer regulären Zeile behandelt werden können. Sie können Elemente vor oder nach ihnen in derselben Zeile haben und unter ihnen einen leeren Bereich haben, dessen Größe von der verwendeten Schriftart und -größe abhängt. Wir möchten keinen leeren Bereich unter unserer Leinwand, also setzen wir den Anzeigemodus einfach auf Block
.
Breite: 100%; Höhe: 100%;
Wie geplant setzen wir die Leinwandmaße auf 100%
der Seitenbreite und -höhe.
Hintergrund: # 888;
Wir haben das schon früher erklärt, nicht wahr?!
Seht das Ergebnis unserer Veränderungen…
…
…
Nein, wir haben nichts falsch gemacht! Das ist völlig normales Verhalten. Erinnern Sie sich an die Maße, die wir der Leinwand in der HTML
Etikett?
Jetzt haben wir der Leinwand andere Dimensionen im CSS gegeben:
Leinwand … Breite: 100%; Höhe: 100%;…
Es stellt sich heraus, dass die von uns im HTML-Tag festgelegten Dimensionen das steuern intrinsische Abmessungen der Leinwand. Die Leinwand ist mehr oder weniger ein Bitmap-Container. Die Abmessungen der Bitmap sind unabhängig davon, wie die Leinwand an ihrer endgültigen Position und den endgültigen Abmessungen auf der Seite angezeigt wird. Was diese definiert, sind die extrinsische Abmessungen, diejenigen, die wir im CSS festlegen.
Wie wir sehen können, wurde unsere kleine 30 * 30-Bitmap so gedehnt, dass sie die gesamte Leinwand ausfüllt. Dies wird vom CSS gesteuert Objekt-fit
Eigenschaft, die standardmäßig verwendet wird füllen
. Es gibt andere Modi, die z. B. statt skalieren, aber seitdem schneiden füllen
kommt uns nicht in die Quere (eigentlich kann es nützlich sein), wir lassen es einfach. Wenn Sie planen, Internet Explorer oder Edge zu unterstützen, können Sie ohnehin nichts dagegen tun. Zum Zeitpunkt der Erstellung dieses Artikels werden sie nicht unterstützt Objekt-fit
überhaupt.
Beachten Sie jedoch, dass die Frage, wie der Browser den Inhalt skaliert, immer noch umstritten ist. Die CSS-Eigenschaft Bild-Rendering
wurde vorgeschlagen, um damit umzugehen, aber es ist immer noch experimentell (wenn überhaupt unterstützt), und es gibt keine bestimmten Skalierungsalgorithmen vor. Nicht nur das, der Browser kann sich dafür entscheiden, es völlig zu vernachlässigen, da dies nur ein Hinweis ist. Dies bedeutet, dass verschiedene Browser vorerst unterschiedliche Skalierungsalgorithmen verwenden, um Ihre Bitmap zu skalieren. Einige von ihnen haben wirklich schreckliche Artefakte, also skalieren Sie nicht zu viel.
Ob wir mit a zeichnen 2d
Kontext oder andere Arten von Kontexten (wie webgl
), die Leinwand verhält sich fast gleich. Wenn wir möchten, dass unsere kleine Bitmap die gesamte Arbeitsfläche ausfüllt und wir nicht gerne dehnen, sollten wir auf Änderungen der Arbeitsflächengröße achten und die Bitmap-Abmessungen entsprechend anpassen. Lass uns das jetzt machen,
Im Hinblick auf die vorgenommenen Änderungen haben wir dem JavaScript diese beiden Zeilen hinzugefügt:
canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight;
Ja, bei der Verwendung 2d
Das Einstellen der internen Bitmap-Bemaßungen auf die Leinwandmaße ist so einfach! Die Leinwand Breite
und Höhe
überwacht werden und wenn einer von ihnen geschrieben wird (selbst wenn es sich um denselben Wert handelt):
Beachten Sie das, um beide einzustellen Breite
und Höhe
, Die obigen Schritte werden ausgeführt zweimal! Einmal beim Wechsel Breite
und der andere beim Wechsel Höhe
. Nein, es gibt keinen anderen Weg, es zu tun, nicht den ich kenne.
Wir haben auch unsere kurze Linie zur neuen Diagonale erweitert,
context.lineTo (canvas.width, canvas.height);
anstatt:
context.lineTo (30, 30);
Da wir die ursprünglichen 30 * 30-Dimensionen nicht mehr verwenden, werden sie im HTML nicht mehr benötigt:
Wir hätten sie auf sehr kleine Werte (wie 1 * 1) initialisieren lassen können, um den Aufwand für das Erstellen einer Bitmap mit den relativ großen Standarddimensionen (300 * 150) zu sparen, sie zu initialisieren, zu löschen und anschließend eine neue zu erstellen richtige Größe setzen wir in JavaScript.
…
auf den zweiten Gedanken, lass uns das einfach tun!
Niemand sollte jemals den Unterschied bemerken, aber ich kann die Schuld nicht ertragen!
Ich hätte gerne gesagt, dass es das ist, aber nicht! offsetWidth
und offsetHeight
werden in CSS-Pixeln angegeben.
Hier ist der Haken. CSS-Pixel sind nicht physikalische Pixel. Sie sind dichteunabhängige Pixel. Abhängig von der physischen Pixeldichte Ihres Geräts (und Ihrem Browser) kann ein CSS-Pixel einem oder mehreren physischen Pixeln entsprechen.
Wenn Sie ein Full-HD-5-Zoll-Smartphone haben, dann ganz offensichtlich offsetWidth
*offsetHeight
wäre 640 * 360 statt 1920 * 1080. Sicher, es füllt den Bildschirm aus, aber da die internen Abmessungen auf 640 * 360 eingestellt sind, ist das Ergebnis eine gestreckte Bitmap, die die hohe Auflösung des Geräts nicht voll ausnutzt. Um dies zu beheben, berücksichtigen wir die devicePixelRatio
:
var pixelRatio = window.devicePixelRatio? window.devicePixelRatio: 1,0; canvas.width = pixelRatio * canvas.offsetWidth; canvas.height = pixelRatio * canvas.offsetHeight;
devicePixelRatio
ist das Verhältnis des CSS-Pixels zum physischen Pixel. Mit anderen Worten, wie viele physische Pixel repräsentiert ein einzelnes CSS-Pixel.
var pixelRatio = window.devicePixelRatio? window.devicePixelRatio: 1,0;
window.devicePixelRatio
wird in den meisten modernen Browsern gut unterstützt. Falls dies jedoch undefiniert ist, werden wir auf den Standardwert von zurückgesetzt 1,0
.
canvas.width = pixelRatio * canvas.offsetWidth; canvas.height = pixelRatio * canvas.offsetHeight;
Durch das Multiplizieren der CSS-Abmessungen mit dem Pixelverhältnis gelangen wir zurück zu den physikalischen Abmessungen. Jetzt hat unsere interne Bitmap genau die gleiche Größe wie die Leinwand, und es kommt zu keiner Dehnung.
Wenn dein devicePixelRatio
ist 1, dann wird es keinen Unterschied geben. Bei jedem anderen Wert ist der Unterschied jedoch signifikant.
Das reicht nicht aus, um die Leinwandgröße zu handhaben. Da wir unsere CSS-Abmessungen relativ zur Seitengröße angegeben haben, wirken sich Änderungen in der Seitengröße auf uns aus. Wenn wir einen Desktop-Browser verwenden, kann der Benutzer das Fenster manuell verkleinern. Wenn wir auf einem mobilen Gerät laufen, unterliegen wir Orientierungsänderungen. Nicht zu erwähnen, dass wir in einem laufen können iframe
das ändert seine Größe beliebig. Um die Größe der internen Bitmap stets korrekt zu halten, müssen wir auf Änderungen in der Seitengröße (Fenstergröße) achten,
Wir haben unseren Code zur Bitmap-Änderung verschoben:
// Erhalte das Pixelverhältnis des Geräts, var pixelRatio = window.devicePixelRatio? window.devicePixelRatio: 1,0; // Anpassen der Leinwandgröße, canvas.width = pixelRatio * canvas.offsetWidth; canvas.height = pixelRatio * canvas.offsetHeight;
Zu einer separaten Funktion, adjustCanvasBitmapSize
:
function adjustCanvasBitmapSize () // Abrufen des Pixelverhältnisses des Geräts, 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;
mit etwas Modifikation. Da wissen wir, wie teuer es ist, Werte zuzuweisen Breite
oder Höhe
Es wäre unverantwortlich, dies unnötig zu tun. Jetzt setzen wir nur noch Breite
und Höhe
wenn sie sich tatsächlich ändern.
Da unsere Funktion auf unsere Leinwand zugreift, erklären wir sie dort, wo sie sie sehen kann. Anfangs wurde es in dieser Zeile erklärt:
var canvas = document.getElementById ("Leinwand");
Dies macht es zu unserem lokalen anonyme Funktion. Wir hätten das einfach entfernen können var
Teil und es wäre geworden global (oder genauer gesagt a Eigentum des globales Objekt, die durch zugänglich ist Fenster
):
canvas = document.getElementById ("canvas");
Ich rate jedoch dringend davon ab Implizite Erklärung. Wenn Sie immer Ihre Variablen deklarieren, vermeiden Sie viel Verwirrung. Stattdessen werde ich es außerhalb aller Funktionen deklarieren:
var Leinwand; var Kontext;
Dies macht es auch zu einer Eigenschaft des globalen Objekts (mit einem kleinen Unterschied, der uns nicht wirklich stört). Es gibt andere Möglichkeiten, um eine globale Variable in diesem StackOverflow-Thread auschecken zu lassen.
Oh, und ich habe mich geschlichen Kontext
auch da oben! Dies wird sich später als nützlich erweisen.
Lassen Sie uns nun unsere Funktion an das Fenster hängen Größe ändern
Veranstaltung:
window.addEventListener ('resize', adjustCanvasBitmapSize);
Von jetzt an, wenn die Fenstergröße geändert wird, adjustCanvasBitmapSize
wird genannt. Da das Fenstergrößenereignis jedoch nicht beim ersten Laden ausgelöst wird, ist unsere Bitmap weiterhin 1 * 1. Deshalb müssen wir anrufen adjustCanvasBitmapSize
einmal von uns.
adjustCanvasBitmapSize ();
Das kümmert sich so ziemlich darum ... außer, wenn Sie die Größe des Fensters ändern, verschwindet die Linie! Versuchen Sie es in dieser Demo.
Zum Glück ist das zu erwarten. Erinnern Sie sich an die durchgeführten Schritte, wenn die Größe der Bitmap geändert wird? Eine davon war, sie mit transparentem Schwarz zu initialisieren. Das ist hier passiert. Die Bitmap wurde mit transparentem Schwarz überschrieben, und jetzt leuchtet der grüne Hintergrund der Leinwand durch. Dies geschieht, weil wir zu Beginn nur einmal zeichnen. Wenn das Größenänderungsereignis stattfindet, wird der Inhalt gelöscht und nicht neu gezeichnet. Das zu beheben sollte einfach sein. Lassen Sie uns die Linie in eine separate Funktion zeichnen:
function drawScene () // Zeichne unsere Linie, context.beginPath (); context.moveTo (0, 0); context.lineTo (canvas.width, canvas.height); context.stroke ();
und rufen Sie diese Funktion von innen auf adjustCanvasBitmapSize
:
// Alles neu zeichnen, drawScene ();
Auf diese Weise wird unsere Szene jedoch immer wieder neu gezeichnet adjustCanvasBitmapSize
heißt, auch wenn keine Dimensionsänderung stattgefunden hat. Um dies zu handhaben, fügen wir eine einfache Überprüfung hinzu:
// Abbruch, wenn sich nichts geändert hat, if (((canvas.width / pixelRatio) == canvas.offsetWidth) && ((canvas.height / pixelRatio) == canvas.offsetHeight)) return;
Überprüfen Sie das Endergebnis:
Versuchen Sie, die Größe hier zu ändern.
Bis jetzt geht es uns gut! Das Ändern der Größe und das erneute Zeichnen von alles kann jedoch sehr teuer werden, wenn Ihre Leinwand ziemlich groß ist und / oder wenn die Szene kompliziert ist. Darüber hinaus kann die Größenänderung des Fensters mit der Maus die Größenänderung von Ereignissen mit hoher Geschwindigkeit auslösen. Deshalb werden wir es drosseln. Anstatt:
window.addEventListener ('resize', adjustCanvasBitmapSize);
wir werden verwenden:
window.addEventListener ( 'die Größe', function onWindowResize (event) // Warten, bis das Ändern der Größe Ereignisse flood absetzt, wenn (onWindowResize.timeoutId) window.clearTimeout (onWindowResize.timeoutId); onWindowResize.timeoutId = window.setTimeout (adjustCanvasBitmapSize, 600 ;);
Zuerst,
window.addEventListener ('resize', Funktion onWindowResize (event) …);
anstatt direkt anzurufen adjustCanvasBitmapSize
wenn der Größe ändern
Ereignis wird ausgelöst, wir haben ein verwendet Funktionsausdruck das gewünschte Verhalten definieren. Im Gegensatz zu der Funktion, die wir zuvor für die verwendet haben Belastung
Ereignis ist diese Funktion a benannte Funktion. Wenn Sie der Funktion einen Namen geben, können Sie sie leicht aus der Funktion heraus referenzieren.
if (onWindowResize.timeoutId) window.clearTimeout (onWindowResize.timeoutId);
Eigenschaften können wie andere Objekte hinzugefügt werden Funktionsobjekte. Anfänglich, timeoutId
ist nicht definiert
, Daher wird diese Anweisung nicht ausgeführt. Seien Sie jedoch vorsichtig bei der Verwendung nicht definiert
und Null
im logische Ausdrücke, weil sie knifflig sein können. Weitere Informationen finden Sie in der ECMAScript-Sprachspezifikation.
Später, timeoutId
wird halten timeoutID von einem adjustCanvasBitmapSize
Auszeit:
onWindowResize.timeoutId = window.setTimeout (adjustCanvasBitmapSize, 600);
Dies verzögert das Aufrufen adjustCanvasBitmapSize
600 Millisekunden nach dem Auslösen des Ereignisses. Das Ereignis kann jedoch nicht ausgelöst werden. Wenn es innerhalb dieser 600 Millisekunden nicht erneut ausgelöst wird, dann adjustCanvasBitmapSize
wird ausgeführt und die Größe der Bitmap wird geändert. Andernfalls, clearTimeout
bricht den geplanten ab adjustCanvasBitmapSize
und setTimeout
plant weitere 600 Millisekunden in der Zukunft. Das Ergebnis ist, solange der Benutzer die Fenstergröße noch ändert, adjustCanvasBitmapSize
wird nicht gerufen Wenn der Benutzer eine Weile anhält oder anhält, wird er aufgerufen. Probieren Sie es aus:
Ähm ... ich meine hier.
Warum 600 Millisekunden? Ich denke, es ist nicht zu schnell und nicht zu langsam, aber vor allem funktioniert es gut, wenn Sie Vollbildanimationen ein- / verlassen, was nicht in diesem Tutorial enthalten ist.
Damit ist unser Tutorial für heute abgeschlossen! Wir haben den gesamten Canvas-spezifischen Code behandelt, den wir zum Einrichten unserer Canvas benötigen. Nächstes Mal, wenn Allah es will, werden wir den WebGL-spezifischen Code behandeln und den Shader ausführen. Bis dahin danke fürs Lesen!