So beherrschen Sie die Bildschirmausrichtung mit HTML5

Wenn Sie einen Artikel im Internet lesen oder eine native Anwendung verwenden, drehen Smartphones und Tablets den Inhalt auf dem Bildschirm um, wenn Sie ihn im Querformat neigen, sodass Sie nicht den Kopf drehen müssen. Bei Web-Spielen mit einem rechteckigen Spielfeld fester Größe kann diese Funktion tatsächlich nachteilig sein. Im Querformat müssen die Spieler möglicherweise die Seite nach unten scrollen, um das Ziel des Gegners zu erreichen. Wenn das Spielfeld verkleinert wird, haben sie nur sehr wenig Platz auf dem Bildschirm, mit dem sie interagieren können.

Als ich ein HTML5-Handyspiel erstellt habe Forex Hockey Ich habe beschlossen, die Ziele immer oben und unten auf dem Gerät zu platzieren. Ich hätte eine 90-Grad-Drehung auf das Spielfeld im Querformat anwenden können, um das Bildlaufproblem zu vermeiden, aber alle Berührungseingabekoordinaten müssten ebenfalls angepasst werden, was einige komplizierte Berechnungen erfordern würde.

Stattdessen habe ich mir die in HTML5 verfügbaren APIs angesehen, um Änderungen der Bildschirmausrichtung zu erkennen oder zu steuern. In diesem Tutorial gehe ich auf die Methoden ein, die ich ausprobiert habe, ihre Vor- und Nachteile und wie Sie sie kombinieren können, um das gewünschte Ergebnis zu erzielen. Die Unterstützung für einige dieser Techniken ist sehr unterschiedlich. Daher habe ich Widgets zur Browserunterstützung hinzugefügt, um Sie zu unterstützen.



CSS-Medienabfragen

Die erste Technik, die ich erforschte, war CSS-Medienabfragen . Sie kennen diese möglicherweise aus dem Responsive Design, bei dem der Inhalt der Seite unterschiedlich angeordnet wird, um bestimmte Browserfenster oder Bildschirmgrößen optimal anzupassen.

Kurz gesagt, mit Medienabfragen können Sie Stile bedingt anwenden. Sie arbeiten, indem sie die CSS-Regeln in einen @ media-Abschnitt einschließen, gefolgt von einer Liste von Funktionen, kombiniert mit logischen Operatoren und oder oder nicht. Browser wenden die in diesem Abschnitt deklarierten Regeln nur an, wenn die Bedingungen erfüllt sind. Die Funktionen reichen von Breite und Höhe bis hin zu Seitenverhältnis, Farbtiefe und Auflösung.

Ich werde mich auf die Orientierungsfunktion konzentrieren, die entweder auf Hoch- oder Querformat eingestellt werden kann:

@media (orientation: portrait) { .playfield { display: block; } .overlay { display: none; } } @media (orientation: landscape) { .playfield { display: none; } .overlay { display: block; } }

In meinem Spiel ist das Element mit einer Spielfeldklasse sichtbar, wenn das Gerät gerade gehalten wird (oder das Desktop-Browserfenster größer als breit ist) und ausgeblendet, wenn es seitlich gehalten wird (oder das Fenster breiter als hoch ist) ). Das Element mit einer Overlay-Klasse, das Spieler dazu verleitet, ihre Geräteorientierung zu ändern, wird ausgeblendet, wenn das Gerät gerade gehalten wird, und sichtbar, wenn dies nicht der Fall ist.

Während diese CSS-Regeln das visuelle Design erreichen, das ich mir vorgenommen habe, gibt es einen Nachteil. Mit dieser Methode würde sich das Spiel weiter auflösen, wenn das Spielfeld ausgeblendet war. Ich kam zu dem Schluss, dass ich auch Code schreiben musste, um das Spiel anzuhalten oder fortzusetzen, wenn sich die Ausrichtung änderte.

Orientierungsänderungsereignisse

Ich entdeckte zusätzliche Eigenschaften und Ereignisse wie window.orientation und orientierungsänderung. Später stellte ich jedoch fest, dass sie einen großen Nachteil hatten. Theoretisch liefert die Fensterorientierung die aktuelle Geräteposition, ausgedrückt als rechter Winkel (entweder -90 °, 0 °, 90 ° oder 180 °). Durch Registrieren eines Ereignishandlers für die Orientierungsänderung beim Fensterobjekt können Sie benachrichtigt werden, wenn diese Eigenschaft den Wert ändert:

window.addEventListener('orientationchange', function() { if (window.orientation == 90 || window.orientation == -90) { game.pause(); // landscape mode } else { game.resume(); // portrait mode } });

Wo ist also der Haken? Sie gehen wahrscheinlich davon aus, dass 0 ° nach oben, -90 ° nach links, 90 ° nach rechts und 180 ° nach oben bedeutet. Dies gilt für iPhone und iPad, da Apple erwartet, dass Sie seine Geräte hauptsächlich im Hochformat verwenden.

Ein Samsung Galaxy S3-Tablet im Hochformat setzt die Fensterorientierung auf 90 °, was mein Code falsch als Querformat interpretiert

Ein Samsung Galaxy S3-Tablet im Hochformat setzt die Fensterorientierung auf 90 °, was mein Code falsch als Querformat interpretiert

Obwohl Android-Handys zum erwarteten Modell passen, enthüllen Tablets eine andere Geschichte. Sie melden 0 °, wenn sie seitlich gehalten werden, da Google davon ausgeht, dass Tablets für andere Zwecke als Smartphones verwendet werden (z. B. zum Ansehen eines Films unterwegs).

Hier ist also die unbequeme Wahrheit: window.orientation ist relativ zur primären Ausrichtung, die vom Gerätehersteller bereitgestellt wird, und daher geräteübergreifend inkonsistent. Aus diesem Grund ist eine vielversprechende Technik eigentlich unzuverlässig. Meiner Meinung nach wird es am besten vermieden.

JavaScript matchMedia

Auf der Suche nach einem Ersatz für die Orientierungsänderungstechnik wandte ich mich an JavaScript matchMedia . Auf diese Weise können Sie die Abfragebedingungen für CSS-Medien zu jedem Zeitpunkt programmgesteuert auswerten. Es kann auch verwendet werden, um Sie über Ereignishandler zu benachrichtigen, wenn sich der Status dieser Bedingungen ändert.

Um zu überprüfen, ob sich ein Gerät derzeit im Querformat befindet, übergebe ich in meinem Fall die Zeichenfolge '(Ausrichtung: Querformat)' an die Funktion window.matchMedia () und überprüfe dann die Übereinstimmungseigenschaft des zurückgegebenen MediaQueryList-Objekts wie folgt:

var query = window.matchMedia('(orientation:landscape)'); console.log('Device held ' + (query.matches ? 'horizontally' : 'vertically'));

Um benachrichtigt zu werden, wenn sich die Geräteorientierung ändert, registriere ich einen Ereignishandler, indem ich addListener () für das im obigen Code erhaltene MediaQueryList-Objekt aufrufe. Die Rückruffunktion empfängt dieses Objekt als Argument, wenn es ausgelöst wird.

var toggleGame = function(query) { if (query.matches) { game.pause(); // landscape mode } else { game.resume(); // portrait mode } } query.addListener(toggleGame);

Wenn ich nicht mehr benachrichtigt werden muss, übergebe ich die gleiche Rückruffunktion an removeListener () für das MediaQueryList-Objekt:

query.removeListener(toggleGame);

Ich finde, dass JavaScript matchMedia CSS-Medienabfragen gut ergänzt. Zusammen helfen sie mir, eine Trennung von Anliegen zu erreichen: Layout versus Code. CSS-Medienabfragen behandeln die visuellen Änderungen, die erforderlich sind, wenn die Ausrichtung geändert wird, während JavaScript matchMedia die Änderungen der Spielelogik übernimmt.

Geräteorientierungs-API

Ich habe auch die bewertet Geräteorientierungs-API . Dies besteht aus zwei Ereignissen, die Informationen von der Hardware liefern, die die Position und Bewegung eines Geräts im Raum messen: Gyroskop und digitaler Kompass für seine Ausrichtung und Beschleunigungsmesser für seine Geschwindigkeit.

CSS-Transformationen drehen Smartphonesymbole gemäß den drei Winkeln Alpha, Beta und Gamma, die von der Geräteorientierungs-API gemessen werden

CSS-Transformationen drehen Smartphonesymbole gemäß den drei Winkeln Alpha, Beta und Gamma, die von der Geräteorientierungs-API gemessen werden

Ich habe Devicemotion-Ereignisse beiseite gelassen, da für mein Spiel keine Geschwindigkeitsmessungen erforderlich sind. Stattdessen habe ich mich ausschließlich auf Geräteorientierungsereignisse konzentriert. Die Orientierungsdaten werden in einer Reihe von Umdrehungen um drei Achsen dargestellt: X, Y und Z. Wenn einem Gerät die Hardware zum Messen eines Winkels fehlt, wird es auf Null gesetzt. Der Rahmen zum Interpretieren dieser Rotationen hängt davon ab, ob DeviceOrientationEvent.absolute wahr oder falsch ist. Wenn dies zutrifft, wird die Erde verwendet: X zeigt nach Osten, Y ist nach Norden und Z ist nach oben. Wenn false, ist es relativ zu einem beliebigen Frame. Macbook Pro-Laptops können beispielsweise angeben, um wie viel sie vorwärts oder rückwärts gekippt und wie stark sie nach links oder rechts geneigt sind. Ihnen fehlt jeglicher Sinn für Kompassrichtung.

  • Alpha ist der Drehwinkel um Z und variiert im Uhrzeigersinn von 0 bis 359 Grad. Es zeigt die entgegengesetzte Richtung eines Kompasskurses an
  • Beta ist der Drehwinkel um X und reicht von -180 bis 179 Grad. Es wird angezeigt, ob das Gerät vorwärts oder rückwärts gekippt ist (der Bildschirm zeigt in einem Winkel von 90 ° zu Ihnen bei -90 ° nach oben, bei 0 ° nach oben und bei -180 ° nach unten).
  • Gamma ist der Drehwinkel um Y und reicht von -90 bis 89 Grad. Es wird gemeldet, ob das Gerät nach links oder rechts geneigt ist
if (window.DeviceOrientationEvent) { window.addEventListener('deviceorientation', function(e) { if (e.absolute) { console.log('Compass heading:', Math.floor(e.alpha)); } }); }

Es ist nicht immer einfach, diese Werte richtig zu interpretieren, da sich die Achsen vertauschen, wenn sich ein Winkel einem rechten Winkelwert nähert (wenn Beta also 90 ° beträgt, zeigt Y nach oben und wird zu Z, Z zeigt nach Süden und wird zu -Y), was sich auswirkt das Gyroskop und digitale Kompassablesungen. Die kleinste Geste lässt Winkel hin und her schwingen, mit großen Wertschwankungen.

Beachten Sie, dass die Geräteorientierungs-API auch eine hohe Anzahl von Ereignissen pro Sekunde generiert. Dies ist nützlich, wenn die Webanwendung in Echtzeit auf jede subtile Bewegung des Geräts reagieren muss. Wenn die Anwendung jedoch nur reagieren muss, wenn der Bildschirm um 90 Grad gedreht wurde (wie dies bei meinem Spiel der Fall ist), ist diese API ein Overkill. Aus diesem Grund habe ich beschlossen, diese API in meinem Spiel nicht zu verwenden.

Lassen Sie uns noch einmal zusammenfassen: Bisher reagiert mein Spiel auf einen Spieler, der seine Geräte in nicht optimalen Positionen hält. Was wäre, wenn es seine ideale Ausrichtung proaktiv durchsetzen könnte?

Bildschirmorientierungs-API

Die nächste Technik, die ich versuchte, war die Bildschirmorientierungs-API . Mit dieser API können Sie drei Dinge tun. Sie können window.screen nach der aktuellen Bildschirmausrichtung abfragen, benachrichtigt werden, wenn sich die Ausrichtung ändert, und eine bestimmte Ausrichtung erzwingen oder die Ausrichtung an das Betriebssystem zurückgeben.

Beim Nexus 6 im Hochformat wurde der Bildschirm durch die Bildschirmausrichtungs-API im Querformat gesperrt

Beim Nexus 6 im Hochformat wurde der Bildschirm durch die Bildschirmausrichtungs-API im Querformat gesperrt

Sie interagieren mit ihm über die Eigenschaft window.screen.orientation (screen ist zufällig auch eine globale Variable und kann direkt aufgerufen werden). Das ScreenOrientation-Objekt verfügt über eine schreibgeschützte Eigenschaft namens type und gibt Folgendes zurück:

  • Porträt-Primär
  • Porträt-Sekundär (verkehrt herum)
  • Porträt (entweder gerade oder verkehrt herum)
  • Querformat-Primär (Gerät ist seitlich, mit der Unterseite des Geräts rechts)
  • Querformat-Sekundär (seitlich mit der Unterseite des Geräts links)
  • Querformat (Unterseite des Geräts entweder links oder rechts)
  • natürlich (Standardausrichtung des Geräteherstellers)
  • any (entsperrt die Ausrichtung und ermöglicht sowohl Hoch- als auch Querformat)

Sie können einen Ereignishandler für ein Änderungsereignis auf screen.orientation registrieren, um über zukünftige Änderungen der Ausrichtung informiert zu werden:

screen.orientation.addEventListener('change', function() { console.log('new orientation is ', screen.orientation.type); });

Sie können den Bildschirm in einer bestimmten Ausrichtung sperren, indem Sie lock () mit einem der unterstützten Ausrichtungstypen aufrufen. lock () gibt ein Versprechen-Objekt zurück, an das Sie einen Erfolgs- und einen Fehlerbehandler anhängen können. Beachten Sie, dass Sie sich im Vollbildmodus befinden müssen, damit der Anruf erfolgreich ist.

var onGameStart = function() { document.documentElement.requestFullscreen(); screen.orientation.lock('portrait').then(null, function(error) { document.exitFullscreen() }); }

Ebenso können Sie den Bildschirm entsperren, damit das Betriebssystem ihn nach Bedarf drehen kann:

document.exitFullscreen(); screen.orientation.unlock();

Die Bildschirmorientierungs-API ist ziemlich neu und befindet sich noch in der Entwicklung. Es ist jedoch die umfassendste Option der sechs Techniken, wenn Sie eine vollständige programmatische Kontrolle über den Bildschirm des Geräts wünschen. Wenn es vom Browser unterstützt wird, habe ich die Bildschirmorientierungs-API verwendet, um sicherzustellen, dass mein Spiel im Hochformat gespielt wird.

Webanwendungsmanifest

Die letzte Option, die ich in Betracht gezogen habe, war die Webanwendungsmanifest . Dies ist nicht zu verwechseln mit dem Offline-Webanwendungsmanifest, das sich auf das Zwischenspeichern von Assets für Zeiten konzentriert, in denen das Netzwerk nicht verfügbar ist.

Das Webanwendungsmanifest soll Webseiten verbessern, die dem Startbildschirm eines Geräts hinzugefügt wurden. Es beschreibt, welches Symbol und welcher Name auf dem Startbildschirm angezeigt wird, ob die Seite in einem normalen Browser oder als eigenständige Anwendung geöffnet wird und auf welche Ausrichtung der Bildschirm beschränkt werden soll.

Fügen Sie zunächst ein Tag hinzu, das auf eine JSON-Datei mit einer Manifestbeziehung verweist:

Zweitens erstellen Sie eine JSON-Datei, die unter anderem die folgenden Einträge enthält:

{ 'display': 'standalone', 'orientation': 'portrait' }

Die Anzeige kann einer der Werte Vollbild, Standalone, Minimal-UI oder Browser sein. Die Ausrichtung kann eine der im Abschnitt API für die Bildschirmausrichtung beschriebenen Ausrichtungstypen sein.

Zuletzt öffnen Sie die Seite in einem Browser und fügen sie dem Homescreen hinzu (in Chrome für Android 'Zum Homescreen hinzufügen' aus dem Seitenmenü).

Anzeige: Vollbild funktioniert unabhängig von der Vollbild-API. Durch Auswerten der CSS-Medienabfrage (Anzeigemodus: Vollbild) mit JavaScript matchMedia kann festgestellt werden, ob der Vollbildmodus als Ergebnis des Webanwendungsmanifests ausgelöst wurde.

if (window.matchMedia('(display-mode: fullscreen)').matches) { console.log('page entered fullscreen mode through the Web Application Manifest'); } else if (document.fullscreenEnabled && document.fullscreenElement) { console.log('page entered fullscreen mode through the Fullscreen API') }

Das Webanwendungsmanifest wird vom Startbildschirm eines Geräts aus gestartet und ist eine sehr einfache Option, wenn Sie die Ausrichtung von Webseiten steuern (aber nicht so sehr abfragen) möchten. Zugegeben, das Aufrufen der Webseite auf den Homescreen des Geräts ist für die Benutzererfahrung unfreundlich, aber die Browserhersteller müssen dies unbedingt verbessern (Google arbeitet daran, die Option anzubieten, regelmäßig besuchte Seiten zum Homescreen hinzuzufügen).

Das Webanwendungsmanifest sperrt mein Spiel im Hochformat, wenn es vom Startbildschirm meines Telefons aus gestartet wird

Das Webanwendungsmanifest sperrt mein Spiel im Hochformat, wenn es vom Startbildschirm meines Telefons aus gestartet wird

Mit dieser Technik konnte ich mit sehr wenig Arbeit von meiner Seite garantieren, dass mein Spiel für Spieler, die es auf ihrem Homescreen gespeichert haben, im Hochformat gespielt wird.

Fazit

Inzwischen sollten Sie mit diesen sechs Techniken vertraut sein, mit denen die Bildschirmausrichtung in Ihrer mobilen Webanwendung erkannt und gesteuert wird, und hoffentlich einige Ideen dazu haben, wofür jede am besten geeignet ist. Wenn Sie sie miteinander kombinieren, erhalten Sie auch eine bessere Abdeckung für die sehr unterschiedliche Browserunterstützung. Der Code für mein Spiel behandelt die Verschlechterung sanft:

  • Das beste Szenario ist, wenn die Bildschirmorientierungs-API verfügbar ist: Sie sperrt das Spiel im Hochformat und die CSS- und JavaScript-Medienabfragen werden nie ausgelöst
  • Der zweitbeste Fall ist, wenn das Spiel vom Homescreen aus gestartet wird: Die Web Manifest API garantiert das gleiche Ergebnis
  • Andernfalls ermutigen CSS-Medienabfragen die Spieler, die Ausrichtung zu korrigieren, während JavaScript matchMedia verhindert, dass sie fehlen, wenn sie das Spiel unterbrechen

Schauen Sie sich meinen CodePen an diese Techniken und lassen Sie mich wissen, wie sie für Sie arbeiten. Ich bin neugierig auf Alternativen, also ruf mich auf Twitter an, wenn du welche kennst!

Wörter :: Jerome Lecomte

Jérôme Lecomte ist Frontend-Entwickler bei OANDA Canada. Dieser Artikel erschien ursprünglich in Ausgabe 270 des Netzmagazins

Mochte dies? Lese das!