Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Ionic 2

Codieren Sie Ihre erste Ionic 2-App: Eine App zum Teilen von Fotos

by
Read Time:28 minsLanguages:

German (Deutsch) translation by Federicco Ancie (you can also view the original English article)

In dieser zweiteiligen Tutorial-Reihe lernen Sie, wie Sie Ihre allererste Ionic 2-App erstellen. Nachdem Sie Ihre Entwicklungsumgebung eingerichtet und den Entwicklungsworkflow in Ionic 2 kennengelernt haben, ist es an der Zeit, sich durch Codierung der App die Hände schmutzig zu machen.

Wenn Sie dies noch nicht getan haben, folgen Sie dem ersten Beitrag, um Ihre Entwicklungsumgebung einzurichten und Ihr Projekt zu booten.

In diesem zweiten Teil werden die Dinge behandelt, die Sie wissen müssen, wenn Sie Apps in Ionic 2 codieren möchten. Sie erfahren, wie Sie Seiten für die App erstellen, Benutzereingaben abrufen und Plugins verwenden, um auf native Funktionen zuzugreifen. Sobald Sie fertig sind, führen Sie die App auf einem Gerät oder Emulator aus. Aber bevor Sie dazu kommen, nehmen wir uns einen Moment Zeit, um darüber zu sprechen, was Sie erstellen werden.

Was Sie erstellen werden

In diesem Tutorial erstellen Sie eine App zum Teilen von Fotos. Der Grundfluss sollte wie folgt sein:

  1. Der Benutzer öffnet die App und meldet sich an. Er wird auf die Seite weitergeleitet, auf der er ein Bild zum Teilen auswählt.
  2. Der Benutzer klickt auf die Schaltfläche Bild auswählen. Die Bildauswahl wird angezeigt und der Benutzer wählt ein Bild aus. Das Bild wird dann in der Vorschau angezeigt.
  3. Der Benutzer gibt eine Beschriftung ein und klickt auf die Schaltfläche Bild teilen, um das Bild an die Instagram-App weiterzuleiten.

Dieses Tutorial zeigt Ihnen nur, wie Sie die App auf einem Android-Gerät ausführen. Cordova (das Framework, auf dem Ionic ausgeführt wird) ist jedoch plattformübergreifend. Ionic 2 verfügt über integrierte Designs für Android, iOS und Windows, sodass Sie auch für diese Geräte problemlos eine Version Ihrer App erstellen können.

So wird die App aussehen:

Completed photo sharing appCompleted photo sharing appCompleted photo sharing app

Projektaufbau

Wenn Sie dem vorherigen Tutorial gefolgt sind, haben Sie bereits Ihre Ionic 2-Entwicklungsumgebung eingerichtet und Ihr Projekt gerüstet. Wir haben die folgenden Ionic 2 CLI-Befehle verwendet, um den Projektordnerbaum zu erstellen und die Bereitstellung für Android vorzubereiten:

Wir haben auch ein paar hilfreiche Plugins installiert:

Codierung der Homepage

Für den Rest des Tutorials arbeiten Sie hauptsächlich im src-Ordner. Nehmen Sie also an, dass der src-Ordner jedes Mal das Stammverzeichnis ist, wenn Sie einen Dateipfad sehen. (Wenn Sie eine Auffrischung der Pfade wünschen, die von der Ionic-Starter-Vorlage erstellt werden, schauen Sie sich das vorherige Tutorial an.)

Im src-Verzeichnis befinden sich vier Ordner:

  • app: Hier wird der App-weite Code definiert. Wenn Sie beim Start der App bestimmten Code ausführen müssen oder das globale CSS aktualisieren möchten, ist dies der richtige Ort.
  • assets: Hier werden Assets wie Bilder abgelegt, die als Inhalt für die App verwendet werden.
  • pages: Hier wird der Code für einzelne Seiten abgelegt. Jede Seite hat einen eigenen Ordner. In jedem Ordner befinden sich drei Dateien, die die Vorlage (HTML), das Styling (CSS) und das Skript (TypeScript) für die Seite definieren.
  • themes: Hier können Sie das Standardthema für Ionic 2 ändern.

Homepage-Vorlage

Standardmäßig enthält die leere Startervorlage für Ionic bereits eine Startseite. Sie müssen es also nur bearbeiten, um den gewünschten Inhalt anzuzeigen. Öffnen Sie die Datei pages/home/home.html und löschen Sie den aktuellen Inhalt. Fügen Sie oben auf der Seite Folgendes hinzu:

Der obige Code ist das Boilerplate für den Header der App. Die Komponente <ion-navbar> dient als Navigationssymbolleiste. Es wird automatisch eine Zurück-Schaltfläche angezeigt, wenn Sie von der Standardseite weg navigieren. <ion-title> legt den Titel der Navigationsleiste fest.

Als nächstes folgt der eigentliche Seiteninhalt. Sie können dies innerhalb der <ion-content>-Komponente definieren. Die Standardauffüllung kann durch Angabe der padding-Option angewendet werden. Erstellen Sie in diesem Container eine neue Liste, die die Eingabefelder zur Eingabe des Benutzernamens und des Kennworts enthält. Das Erstellen einer Liste mit Bearbeitungsfeldern ist eine Standardpraxis in Ionic. Sie können jedes Feld sauber übereinander stapeln. Unterhalb der Liste befindet sich die Schaltfläche zum Anmelden.

Nehmen wir uns einen Moment Zeit, um den Code für die Texteingabe und das Klicken auf eine Schaltfläche zu betrachten. In Ionic können Sie Texteingabefelder mit der Komponente <ion-input> definieren. Verwenden Sie [(ngModel)], um das Textfeld an eine in Ihrem Seitenskript definierte Klasseneigenschaft zu binden. Der ihm zugewiesene Wert ist dann der Name der Klasseneigenschaft.

Um die bidirektionale Datenbindung einzurichten, können Sie [value] auf denselben Eigenschaftsnamen setzen, der für [(ngModel)] verwendet wird. Auf diese Weise können Sie den Wert des Textfelds aktualisieren, indem Sie den Wert des Modells im Seitenskript ändern. Später erfahren Sie, wie Sie eine Klasseneigenschaft im Seitenskript definieren.

Verwenden Sie zum Definieren von Schaltflächen das Standard button-Element in HTML. Wenn Sie sich fragen, warum es nicht <ion-button> ist, liegt dies an Gründen der Barrierefreiheit. Schaltflächen sind eine wichtige Schnittstelle. Daher hat sich das Ionic-Team entschlossen, die Standard-HTML-Schaltflächen beizubehalten, um sie zugänglich zu machen. Die ion-button-Direktive wird stattdessen hinzugefügt, um zusätzliche Funktionen bereitzustellen.

Ionic 2 buttonsIonic 2 buttonsIonic 2 buttons

Um einen Klick-Handler hinzuzufügen, verwenden Sie die (click)-Direktive, wobei ein Wert die Funktion angibt (die in Ihrem Seitenskript definiert ist), die ausgeführt werden soll, wenn das Klickereignis auftritt.

Homepage-Skript

Öffnen Sie die Datei pages/home/home.ts, löschen Sie den gesamten Inhalt und fügen Sie Folgendes hinzu:

Wenn wir den obigen Code aufschlüsseln, importieren wir zuerst die Angular-Komponentenklasse, in die alle Ionic-Direktiven bereits eingebrannt sind.

Als nächstes importieren wir die Controller für Navigation und Warnungen aus dem ionic-angular paket. Hier sind alle Ionic-Controller enthalten.

Danach importieren wir die PickerPage. Sie werden es später erstellen, lassen Sie es also vorerst auskommentiert. Denken Sie daran, den Kommentar zu entfernen, sobald Sie ihn laden möchten.

Verwenden Sie nach dem Import den @Component-Dekorator, um die vom Skript zu verwendende HTML-Vorlage anzugeben:

Jetzt können wir die Klasse für unser Homepage-Skript definieren. Wir möchten diese Klasse exportieren, damit sie aus anderen Dateien in der App importiert werden kann.

Stellen Sie den NavController und den AlertController in der gesamten Klasse zur Verfügung, indem Sie sie als Parameter im constructor definieren. Auf diese Weise können Sie this.navCtrl verwenden, wenn Sie beispielsweise mit dem NavController zu einer anderen Seite navigieren möchten.

Jetzt können wir Eigenschaften unseres Controllers definieren, auf die in der Vorlage verwiesen werden kann. Diese Eigenschaften enthalten den aktuellen Wert des Textfelds für Benutzername und Passwort:

Um die Dinge einfach zu halten, verwenden wir fest codierte Werte für den Benutzernamen und das Passwort. Bei realen Apps stellen Sie normalerweise eine Anfrage an einen Server, um den Benutzer zu authentifizieren.

Erstellen Sie in der Funktion login() eine Warnung, wenn der Benutzer einen falschen Benutzernamen oder ein falsches Kennwort eingibt:

Wenn die Anmeldeinformationen falsch sind, zeigen Sie die Warnung an:

Ionic 2 alertsIonic 2 alertsIonic 2 alerts

Wenn der vom Benutzer eingegebene Benutzername und das Kennwort mit den fest codierten Werten übereinstimmen, verwenden Sie den NavController, um die Auswahlseite in den Navigationsstapel zu verschieben. Unabhängig davon, welche Seite Sie in den Navigationsstapel verschieben, wird sie zur aktuellen Seite, während das Popup einer Seite effektiv zur vorherigen Seite navigiert. So funktioniert die Navigation in Ionic 2.

Auswahlseite

Als Nächstes müssen Sie die Auswahlseite erstellen. Wie Sie bereits wissen, besteht der Standard darin, für jede Seite einen eigenen Ordner zu erstellen, und jeder Ordner enthält drei Dateien. Zum Glück enthält die Ionic CLI auch einen Befehl, mit dem wir neue Seiten erstellen können:

Dies verwendet den Befehl generate, mit dem der Seitenordner mit diesen drei Dateien erstellt wird. Das Beste ist, dass jede Datei bereits einen Boilerplate-Code enthält, mit dem Sie beginnen können.

Auswahlseitenvorlage

Öffnen Sie anschließend die Datei pages/picker/picker.html und ersetzen Sie den Boilerplate-Code durch den folgenden:

Keiner dieser Codes ist wirklich unbekannt, außer der hidden Direktive und der Verwendung einer <ion-card>-Komponente.

Mit der Anweisung hidden können Sie ein Element basierend auf einem bestimmten Wert ausblenden, der in Ihrem Seitenskript definiert ist. Wenn also has_picked_image true ist, ist dieses div nur dann sichtbar.

Die <ion-card>-Komponente wird zum Erstellen von cards verwendet. Karten sind eine großartige Möglichkeit, Bilder in Apps anzuzeigen.

Ionic 2 card imagesIonic 2 card imagesIonic 2 card images

Picker-Seitenstil

Öffnen Sie die Datei pages/picker/picker.scss und fügen Sie Folgendes hinzu:

Auswahlseiten-Skript

Öffnen Sie die Datei pages/picker/picker.ts und fügen Sie Folgendes hinzu:

Ich werde das ein bisschen aufschlüsseln. Zuerst importieren wir die Plugins, die Sie zuvor installiert haben. Beachten Sie, dass die Plugins alle unter demselben Paket installiert sind (ionic-native). Das ist wirklich schön, denn anstatt jedes einzelne Plugin in eine eigene Zeile importieren zu müssen, können Sie es einfach in einer einzelnen Zeile tun.

Als nächstes deklarieren wir die Klasseneigenschaften:

Wenn Sie auf die Schaltfläche Bild auswählen klicken, definieren Sie die Optionen für die Bildauswahl. Diese Optionen sind ziemlich selbsterklärend, aber ich habe einige Kommentare hinzugefügt, um zu verdeutlichen, was die einzelnen Optionen tun.

Das Angeben der width und height bedeutet nicht unbedingt, dass das resultierende Bild genau diese Breite und Höhe verwendet. Dies bedeutet, dass Ionic diese Abmessungen als maximale Breite oder Höhe verwendet, sodass das Seitenverhältnis weiterhin erhalten bleibt.

Wir verwenden Daten-URI als Ausgabetyp, da das Instagram-Plugin nur Daten-URIs akzeptiert. Dies bedeutet, dass Sie auch die Breite, Höhe und Qualität auf das Nötigste einstellen müssen, da Daten-URIs bei hoher Qualität sehr lang sein können - das gesamte Bild wird in einer URI-Zeichenfolge codiert! Dies kann zum Absturz der App führen. Daher ist es immer empfehlenswert, bei der Arbeit mit Daten-URIs bei geringerer Qualität und kleineren Bildern zu bleiben.

Verwenden Sie als Nächstes das Image Picker-Plugin, um den Bildauswahlbildschirm auszulösen. Da wir nur ein einzelnes Bild erwarten, können wir einfach auf das erste Element im Ergebnisarray zugreifen. Wir müssen auch das Präfix für Daten-URIs voranstellen.

Wenn Sie schließlich auf die Schaltfläche Bild freigeben klicken, wird durch die vom Instagram-Plugin bereitgestellte share-Methode der Freigabebildschirm in der Instagram-App gestartet. Das Bild ist bereits vorgefüllt.

Die Beschriftung wird jedoch nicht kopiert. Die Instagram-App hat vorab ausgefüllte Untertitel deaktiviert, sodass das Beschriftungsfeld nach dem Öffnen der Instagram-App leer ist. Um dieses Problem zu umgehen, kopiert das Instagram-Plugin die Beschriftung stattdessen in die Zwischenablage. Dies bedeutet, dass der Benutzer es stattdessen einfach in das Beschriftungstextfeld in der Instagram-App einfügen kann.

Alles zusammenbringen

Der letzte Schritt ist das Öffnen der Datei app/app.module.ts. Dies ist das Stammmodul der App, in dem Sie alle Seiten und Anbieter definieren (z. B. den Standard-Ionic-Fehlerbehandler), die Sie in der gesamten App verwenden werden.

Stellen Sie sicher, dass alle von Ihnen erstellten Seiten definiert sind. Andernfalls wird eine Fehlermeldung angezeigt, wenn Sie zu einer Seite navigieren, die nicht definiert wurde. Standardmäßig ist die HomePage hier bereits definiert, sodass Sie nur die PickerPage hinzufügen müssen. Importieren Sie es einfach oben in die Datei und fügen Sie es dann unter dem Array declarations und entryComponents hinzu. Beachten Sie, dass MyApp keine Seite ist. Es ist eine Komponente, die als leere Shell für die Seiten dient, in die geladen werden soll.

Wenn Sie die Datei app/app.components.ts öffnen, wird Folgendes angezeigt:

Hier können Sie die Stammseite definieren - die Seite, die der Benutzer beim Öffnen der App sieht. In diesem Fall ist die HomePage die Stammseite. Dies ist auch perfekt für die Ausführung von Initialisierungscode, da der Code hier nur einmal ausgeführt wird, wenn der Benutzer die App startet. Wenn Sie etwas initialisieren (z. B. um Erlaubnis bitten, Bluetooth zu aktivieren), sollten Sie immer warten, bis das Ereignis platform.ready() ausgelöst wird. Erst wenn dieses Ereignis ausgelöst wurde, können Sie sicher sein, dass native Funktionen aufgerufen werden können.

Ausführen der App

Jetzt können Sie die App auf einem mobilen Gerät oder Emulator ausführen. Sie können dies tun, indem Sie den folgenden Befehl ausführen:

Stellen Sie sicher, dass Sie ein Gerät an Ihren Computer angeschlossen haben oder dass eine Instanz eines Emulators ausgeführt wird, wenn Sie den obigen Befehl ausführen. Wenn es immer noch nicht funktioniert, überprüfen Sie, ob Sie das USB-Debugging auf Ihrem Gerät aktiviert haben, und führen Sie adb devices aus. Dadurch wird Ihr Computer dazu veranlasst, eine Verbindung zu Ihrem Gerät herzustellen. Stimmen Sie einfach der Eingabeaufforderung in Ihrem Gerät zu, sobald Sie die Authentifizierungsaufforderung sehen.

Wenn Sie eine Kopie der APK-Datei haben möchten, damit Sie sie für einen Freund freigeben können, können Sie eine generieren, indem Sie stattdessen Folgendes ausführen:

Dadurch wird eine android-debug.apk-Datei im Ordner platform/android/build/output/apk erstellt.

Abschluss

Das ist es! In diesem Tutorial haben Sie Ihre allererste Ionic 2-App erstellt. Es ist eine einfache App, und Sie haben es vielleicht sogar leicht gefunden. Sie haben jedoch gelernt, wie Sie eine Umgebung für die Entwicklung von Ionic 2-Apps einrichten, und Sie haben einige grundlegende Konzepte kennengelernt, die Sie bei der zukünftigen Entwicklung von Apps anwenden können. Dazu gehören das Abrufen des aktuellen Werts aus einem Textfeld, das Reagieren auf Klickereignisse, das Verknüpfen von Bildern und die Verwendung von Plugins für den Zugriff auf native Funktionen. Also klopfe dir auf den Rücken! Du hast gute Arbeit geleistet, um so weit zu kommen.

In der Zwischenzeit können Sie einige unserer anderen Tutorials zu Ionic 2 lesen!

Wenn Sie eine ausführliche und praktische Einführung in das Ionic 2-Framework wünschen, versuchen Sie unseren Kurs Erste Schritte mit Ionic 2.

In diesem Kurs wird Reggie Dawson Ihnen alles über das Ionic-Framework beibringen und Ihnen zeigen, wie Sie eine mobile App von Grund auf neu erstellen. Unterwegs erfahren Sie mehr über die Ionic-Komponentenbibliothek, über das Programmieren von statisch typisiertem JavaScript mit TypeScript und über die Integration einer Ionic 2-App in eine Rich Media-API.



Erste Schritte in WebGL, Teil 4: WebGL-Ansichtsfenster und Clipping

In den vorherigen Teilen dieser Serie haben wir viel über Shader, das Canvas-Element, WebGL-Kontexte und darüber gelernt, wie der Browser unseren Farbpuffer über den Rest der Seitenelemente zusammensetzt.

In diesem Artikel schreiben wir weiter unseren WebGL-Boilerplate-Code. Wir bereiten unsere Leinwand noch für das Zeichnen mit WebGL vor, diesmal unter Berücksichtigung von Ansichtsfenstern und Grundelementen.

Dieser Artikel ist Teil der Reihe "Erste Schritte in WebGL". Wenn Sie die vorherigen Teile nicht gelesen haben, empfehle ich, sie zuerst zu lesen:

  1. Einführung in Shader
  2. Das Canvas-Element für unseren ersten Shader
  3. WebGL-Kontext und Löschen

Rekapitulieren

  • Im ersten Artikel dieser Serie haben wir einen einfachen Shader geschrieben, der einen farbenfrohen Farbverlauf zeichnet und ihn leicht ein- und ausblendet.
  • Im zweiten Artikel dieser Reihe haben wir begonnen, diesen Shader auf einer Webseite zu verwenden. In kleinen Schritten erklärten wir den notwendigen Hintergrund des Canvas-Elements.
  • Im dritten Artikel haben wir unseren WebGL-Kontext erfasst und ihn zum Löschen des Farbpuffers verwendet. Wir haben auch erklärt, wie sich die Leinwand mit den anderen Elementen der Seite verbindet.

In diesem Artikel fahren wir dort fort, wo wir abgereist sind, und lernen diesmal die WebGL-Ansichtsfenster und deren Auswirkungen auf das Abschneiden von Grundelementen kennen.

Als nächstes in dieser Reihe werden wir - wenn Allah will - unser Shader-Programm kompilieren, mehr über WebGL-Puffer erfahren, Grundelemente zeichnen und das Shader-Programm ausführen, das wir im ersten Artikel geschrieben haben. Fast dort!

Leinwandgröße

Das ist unser bisheriger Code:

Beachten Sie, dass ich die CSS-Hintergrundfarbe auf Schwarz und die klare Farbe auf undurchsichtiges Rot zurückgesetzt habe.

Dank unseres CSS haben wir eine Leinwand, die sich erstreckt, um unsere Webseite zu füllen, aber der zugrunde liegende 1x1-Zeichenpuffer ist kaum nützlich. Wir müssen eine richtige Größe für unseren Zeichenpuffer einstellen. Wenn der Puffer kleiner als die Zeichenfläche ist, wird die Auflösung des Geräts nicht vollständig genutzt und es treten Skalierungsartefakte auf (wie in einem vorherigen Artikel erläutert). Wenn der Puffer größer als die Leinwand ist, kommt die Qualität tatsächlich sehr zugute! Aufgrund des Super-Sampling-Anti-Aliasing verkleinert der Browser den Puffer, bevor er an den Compositor übergeben wird.

Die Leistung nimmt jedoch einen guten Schlag. Wenn Anti-Aliasing gewünscht wird, wird dies besser durch MSAA (Multi-Sampling-Anti-Aliasing) und Texturfilterung erreicht. Im Moment sollten wir einen Zeichenpuffer mit der gleichen Größe unserer Leinwand anstreben, um die Auflösung des Geräts voll auszunutzen und eine Skalierung insgesamt zu vermeiden.

Dazu leihen wir uns die adjustCanvasBitmapSize aus Teil 2 aus (mit einigen Modifikationen):

Änderungen:

  • Wir haben clientWidth und clientHeight anstelle von offsetWidth und offsetHeight verwendet. Letztere enthalten die Leinwandränder, sodass sie möglicherweise nicht genau das sind, wonach wir suchen. clientWidth und clientHeight sind für diesen Zweck besser geeignet. Mein Fehler!
  • adjustDrawingBufferSize soll jetzt nur ausgeführt werden, wenn Änderungen vorgenommen wurden. Daher müssen wir nicht explizit prüfen und abbrechen, wenn sich nichts geändert hat.
  • Wir müssen drawScene nicht mehr jedes Mal aufrufen, wenn sich die Größe ändert. Wir werden sicherstellen, dass es regelmäßig woanders aufgerufen wird.
  • Ein glContext.viewport wurde angezeigt! Es bekommt einen eigenen Abschnitt, also lass es jetzt passieren!

Wir leihen uns auch die Drosselungsfunktion für Größenänderungsereignisse aus, onWindowResize (mit einigen Änderungen auch):

Änderungen:

  • Es ist jetzt onCanvasResize anstelle von onWindowResize. In unserem Beispiel ist es in Ordnung anzunehmen, dass sich die Leinwandgröße nur ändert, wenn die Fenstergröße geändert wird. In der realen Welt kann unsere Leinwand jedoch Teil einer Seite sein, auf der andere Elemente vorhanden sind, deren Größe geändert werden kann und die sich auf unsere Leinwandgröße auswirken.
  • Anstatt die Ereignisse im Zusammenhang mit Änderungen der Canvas-Größe abzuhören, werden wir jedes Mal, wenn wir den Canvas-Inhalt neu zeichnen, nach Änderungen suchen. Mit anderen Worten, onCanvasResize wird aufgerufen, unabhängig davon, ob Änderungen aufgetreten sind oder nicht. Daher ist ein Abbruch erforderlich, wenn sich nichts geändert hat.

Rufen wir nun onCanvasResize von drawScene aus auf:

Ich erwähnte, dass wir drawScene regelmäßig anrufen werden. Dies bedeutet, dass wir kontinuierlich rendern, nicht nur wenn Änderungen auftreten (auch bekannt als Dirty). Das Zeichnen verbraucht kontinuierlich mehr Strom als das Zeichnen nur, wenn es schmutzig ist. Es erspart uns jedoch die Mühe, nachverfolgen zu müssen, wann der Inhalt aktualisiert werden muss.

Es lohnt sich jedoch zu überlegen, ob Sie eine Anwendung erstellen möchten, die über einen längeren Zeitraum ausgeführt wird, z. B. Hintergrundbilder und Starter (dies würden Sie jedoch zunächst nicht in WebGL tun, oder?). Daher werden wir in diesem Tutorial kontinuierlich rendern. Der einfachste Weg, dies zu tun, besteht darin, die erneute Ausführung von drawScene von sich aus zu planen:

Nein, wir haben dafür weder setInterval noch setTimeout verwendet. requestAnimationFrame teilt dem Browser mit, dass Sie eine Animation ausführen möchten, und fordert auf, drawScene vor dem nächsten Repaint aufzurufen. Es ist am besten für Animationen unter den dreien geeignet, weil:

  • Die Timings von setInterval und setTimeout werden oft nicht genau eingehalten - sie basieren auf Best-Effort. Bei requestAnimationFrame entspricht das Timing im Allgemeinen der Aktualisierungsrate der Anzeige.
  • Wenn der geplante Code Änderungen im Layout des Seiteninhalts enthält, können setInterval und setTimeout zu Layout-Thrashing führen (dies ist jedoch nicht der Fall). requestAnimationFrame kümmert sich darum und löst keine unnötigen Reflow- und Repaint-Zyklen aus.
  • Mit requestAnimationFrame kann der Browser entscheiden, wie oft unsere Animations- / Zeichenfunktion aufgerufen werden soll. Dies bedeutet, dass es gedrosselt werden kann, wenn die Seite / der Iframe ausgeblendet oder inaktiv wird, was eine längere Akkulaufzeit für mobile Geräte bedeutet. Dies passiert auch mit setInterval und setTimeout in mehreren Browsern (Firefox, Chrome) - tun Sie einfach so, als ob Sie es nicht wissen!

Zurück zu unserer Seite. Jetzt ist unser Größenänderungsmechanismus abgeschlossen:

  • drawScene wird regelmäßig aufgerufen und ruft jedes Mal onCanvasResize auf.
  • onCanvasResize überprüft die Canvas-Größe. Wenn Änderungen vorgenommen wurden, plant es einen Aufruf von adjustDrawingBufferSize oder verschiebt ihn, wenn er bereits geplant war.
  • adjustDrawingBufferSize ändert tatsächlich die Größe des Zeichenpuffers und legt dabei die neuen Abmessungen des Ansichtsfensters fest.

Alles zusammenfügen:

Ich habe eine Warnung hinzugefügt, die jedes Mal angezeigt wird, wenn die Größe des Zeichenpuffers geändert wird. Möglicherweise möchten Sie das obige Beispiel in einer neuen Registerkarte öffnen und die Fenstergröße ändern oder die Geräteausrichtung ändern, um es zu testen. Beachten Sie, dass die Größe nur geändert wird, wenn Sie die Größenänderung für 0,6 Sekunden gestoppt haben (als würden Sie das messen!).

Eine letzte Bemerkung, bevor wir diese Sache mit der Puffergröße beenden. Es gibt Grenzen, wie groß ein Zeichenpuffer sein kann. Diese hängen von der verwendeten Hardware und dem verwendeten Browser ab. Wenn Sie zufällig sind:

  • mit einem Smartphone oder
  • ein lächerlich hochauflösender Bildschirm oder
  • mehrere Monitore/Arbeitsbereiche/virtuelle Desktops eingestellt haben, oder
  • verwenden ein Smartphone oder
  • Zeigen Sie Ihre Seite in einem sehr großen Iframe an (was der einfachste Weg ist, dies zu testen), oder
  • verwenden ein Smartphone

Es besteht die Möglichkeit, dass die Größe der Leinwand auf mehr als die möglichen Grenzen geändert wird. In diesem Fall zeigen die Breite und Höhe der Leinwand keine Einwände, aber die tatsächliche Puffergröße wird auf das maximal mögliche Maß geklemmt. Sie können die tatsächliche Puffergröße mit den schreibgeschützten Elementen glContext.drawingBufferWidth und glContext.drawingBufferHeight ermitteln, mit denen ich die Warnung erstellt habe.

Abgesehen davon sollte alles gut funktionieren... außer dass in einigen Browsern Teile von dem, was Sie zeichnen (oder alles), möglicherweise nie auf dem Bildschirm landen! In diesem Fall kann es sinnvoll sein, diese beiden Zeilen nach der Größenänderung zu adjustDrawingBufferSize hinzuzufügen:

Jetzt sind wir wieder da, wo Dinge Sinn machen. Beachten Sie jedoch, dass das Festklemmen an drawBufferWidth und drawingBufferHeight möglicherweise nicht die beste Aktion ist. Möglicherweise möchten Sie ein bestimmtes Seitenverhältnis beibehalten.

Jetzt lass uns zeichnen!

Ansichtsfenster und Scheren

Denken Sie daran, dass WebGL im ersten Artikel dieser Serie erwähnt hat, dass WebGL im Shader die Koordinaten (-1, -1) verwendet, um die untere linke Ecke Ihres Ansichtsfensters darzustellen, und (1, 1), um die obere rechte Ecke darzustellen. Das ist es. Das viewport teilt WebGL mit, welches Rechteck in unserem Zeichenpuffer (-1, -1) und (1, 1) zugeordnet werden soll. Es ist nur eine Transformation, nichts weiter. Es wirkt sich nicht auf Puffer oder ähnliches aus.

Ich habe auch gesagt, dass alles außerhalb der Abmessungen des Ansichtsfensters übersprungen und nicht vollständig gezeichnet wird. Das ist fast völlig richtig, hat aber eine Wendung. Der Trick liegt in den Worten "gezeichnet" und "draußen". Was zählt wirklich als Zeichnen oder als Außen?

Diese Linie begrenzt unser Ansichtsfenster-Rechteck auf die linke Hälfte der Leinwand. Ich habe es der drawScene-Funktion hinzugefügt. Normalerweise müssen wir das viewport nicht aufrufen, es sei denn, die Größe der Zeichenfläche ändert sich, und wir haben es tatsächlich dort getan. Sie können die in der Größenänderungsfunktion löschen, aber ich lasse es einfach. Versuchen Sie in der Praxis, Ihre WebGL-Aufrufe so gering wie möglich zu halten. Mal sehen, was diese Zeile macht:

Oh, clear(glContext.COLOR_BUFFER_BIT) hat unsere Einstellungen für das Ansichtsfenster völlig ignoriert! Das ist es, duh! Das viewport hat keinerlei Auswirkungen auf eindeutige Anrufe. Die Abmessungen des Ansichtsfensters wirken sich auf das Abschneiden von Grundelementen aus. Denken Sie daran, dass ich im ersten Artikel gesagt habe, dass wir in WebGL nur Punkte, Linien und Dreiecke zeichnen können. Diese werden so an den Abmessungen des Ansichtsfensters abgeschnitten, wie Sie es für möglich halten... mit Ausnahme von Punkten.

Punkte

Ein Punkt wird vollständig gezeichnet, wenn sein Zentrum innerhalb der Dimensionen des Ansichtsfensters liegt, und wird vollständig weggelassen, wenn sein Zentrum außerhalb dieser Dimensionen liegt. Wenn ein Punkt fett genug ist, kann sich seine Mitte immer noch im Ansichtsfenster befinden, während sich ein Teil davon nach außen erstreckt. Dieser ausziehbare Teil sollte gezeichnet werden. So sollte es sein, aber das ist in der Praxis nicht unbedingt der Fall:

Sie sollten etwas Ähnliches sehen, wenn Ihr Browser, Ihr Gerät und Ihre Treiber (in dieser Hinsicht) den Standard einhalten:

Die Größe der Punkte hängt von der tatsächlichen Auflösung Ihres Geräts ab. Beachten Sie also nicht den Größenunterschied. Achten Sie einfach darauf, wie viele Punkte angezeigt werden. Im obigen Beispiel habe ich den Ansichtsfensterbereich auf den mittleren Bereich der Leinwand (den Bereich mit dem Farbverlauf) festgelegt. Da sich die Mittelpunktsbereiche der Punkte jedoch noch im Ansichtsfenster befinden, sollten sie vollständig gezeichnet werden (die grünen Elemente). Wenn dies in Ihrem Browser der Fall ist, dann großartig! Aber nicht alle Benutzer haben so viel Glück. Einige Benutzer sehen die Außenteile wie folgt beschnitten:

Meistens macht es wirklich keinen Unterschied. Wenn das Ansichtsfenster die gesamte Leinwand abdeckt, ist es uns egal, ob die Außenseiten gekürzt werden oder nicht. Aber es wäre wichtig, wenn sich diese Punkte reibungslos außerhalb der Leinwand bewegen würden, und dann verschwanden sie plötzlich, weil ihre Zentren nach draußen gingen:

(Drücken Sie Ergebnis, um die Animation neu zu starten.)

Auch dieses Verhalten ist nicht unbedingt das, was Sie sehen. Laut der Geschichte schneiden Nvidia-Geräte die Punkte nicht ab, wenn ihre Zentren nach draußen gehen, sondern schneiden die Teile, die nach draußen gehen. Auf meinem Computer (mit einem AMD-Gerät) verhalten sich Chrome, Firefox und Edge unter Windows gleich. Auf demselben Computer schneiden Chrome und Firefox die Punkte jedoch ab und schneiden sie nicht ab, wenn sie unter Linux ausgeführt werden. Auf meinem Android-Handy schneiden und schneiden Chrome und Firefox die Punkte!

Scheren

Es scheint, dass das Zeichnen von Punkten störend ist. Warum sich überhaupt darum kümmern? Weil Punkte nicht kreisförmig sein müssen. Sie sind achsenausgerichtete rechteckige Bereiche. Es ist der Fragment-Shader, der entscheidet, wie sie gezeichnet werden. Sie können texturiert werden. In diesem Fall werden sie als Punkt-Sprites bezeichnet. Diese können verwendet werden, um viele Dinge zu erstellen, wie Kachelkarten und Partikeleffekte, in denen sie sehr praktisch sind, da Sie nur einen Scheitelpunkt pro Sprite (die Mitte) übergeben müssen, anstatt vier im Fall eines Dreiecksstreifens . Das Reduzieren der von der CPU zur GPU übertragenen Datenmenge kann sich in komplexen Szenen wirklich auszahlen. In WebGL 2 können wir die Geometrieinstanzierung verwenden (die ihre eigenen Fänge hat), aber wir sind noch nicht da.

Wie gehen wir mit dem Abschneiden von Punkten um? Um die äußeren Teile zu beschneiden, verwenden wir eine Schere:

Das Scheren ist jetzt aktiviert. So legen Sie den Scherenbereich fest:

Während die Positionen der Grundelemente relativ zu den Abmessungen des Ansichtsfensters sind, sind dies die Abmessungen des Scherenkastens nicht. Sie geben ein Rohrechteck im Zeichenpuffer an, unabhängig davon, wie stark es das Ansichtsfenster überlappt (oder nicht). Im folgenden Beispiel habe ich das Ansichtsfenster und die Scherenbox auf den mittleren Bereich der Leinwand eingestellt:

(Drücken Sie Ergebnis, um die Animation neu zu starten.)

Beachten Sie, dass der Scherentest eine Operation pro Probe ist, bei der die Fragmente verworfen werden, die außerhalb der Testbox liegen. Es hat nichts mit dem zu tun, was gezeichnet wird; es verwirft nur die Fragmente, die nach draußen gehen. Auch clear respektiert der Scherentest! Deshalb ist die blaue Farbe (die klare Farbe) an die Scherenbox gebunden. Alles, was bleibt, ist zu verhindern, dass die Punkte verschwinden, wenn ihre Zentren nach draußen gehen. Dazu stelle ich sicher, dass das Ansichtsfenster größer als die Scherenbox ist und einen Rand aufweist, mit dem die Punkte noch gezeichnet werden können, bis sie sich vollständig außerhalb der Scherenbox befinden:

(Drücken Sie Ergebnis, um die Animation neu zu starten.)

Yay! Das sollte überall gut funktionieren. Im obigen Code haben wir jedoch nur einen Teil der Leinwand zum Zeichnen verwendet. Was wäre, wenn wir die ganze Leinwand einnehmen wollten? Es macht wirklich keinen Unterschied. Das Ansichtsfenster kann problemlos größer als der Zeichenpuffer sein (ignorieren Sie einfach Firefox 'Beschimpfungen in der Konsolenausgabe):

Sehen:

Beachten Sie jedoch die Größe des Ansichtsfensters. Auch wenn das Ansichtsfenster nur eine Transformation ist, die Sie keine Ressourcen kostet, möchten Sie sich nicht nur auf das Abschneiden pro Probe verlassen. Ändern Sie das Ansichtsfenster nur bei Bedarf und stellen Sie es für den Rest der Zeichnung wieder her. Und denken Sie daran, dass das Ansichtsfenster die Position der Grundelemente auf dem Bildschirm beeinflusst. Berücksichtigen Sie dies auch.

Das war es fürs Erste! Lassen Sie uns das nächste Mal die gesamte Größe, das Ansichtsfenster und die Ausschnitte hinter uns lassen. Auf zum Zeichnen einiger Dreiecke! Vielen Dank für das Lesen und ich hoffe, es war hilfreich.

Verweise

Advertisement
Did you find this post useful?
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.