Verwendung der Window Management API
Diese Anleitung erklärt, wie Sie die Window Management API verwenden. Der unten gezeigte Beispielcode stammt aus unserem Multi-window Lernumgebung Beispiel (siehe den Quellcode).
Feature-Erkennung
Sie können die Window Management API erkennen, indem Sie auf das Vorhandensein von getScreenDetails
in der aktuellen window
Instanz überprüfen. Beispielsweise möchten Sie vielleicht einen Button bereitstellen, um eine Multi-Window-Darstellung zu öffnen, wenn die API unterstützt wird, oder ein anderes Erlebnis bieten, wie das Erstellen von Links zu den verschiedenen Seiten, wenn dies nicht der Fall ist:
if ("getScreenDetails" in window) {
// The Window Management API is supported
createButton();
} else {
// The Window Management API is not supported
createLinks(sites);
}
Grundlegende Verwendung
Kernstück der Windows Management API ist die Methode Window.getScreenDetails()
, die ein Objekt mit Details zu allen auf dem System des Nutzers verfügbaren Bildschirmen zurückgibt:
const screenDetails = await window.getScreenDetails();
// Return the number of screens
const noOfScreens = screenDetails.screens.length;
Wenn getScreenDetails()
aufgerufen wird, wird der Nutzer um Erlaubnis gefragt, Fenster auf allen seinen Bildschirmen zu verwalten (der Status dieser Berechtigung kann mit Permissions.query()
abgefragt werden, um window-management
zu erfragen). Wenn der Nutzer die Erlaubnis erteilt, wird ein ScreenDetails
Objekt zurückgegeben. Dieses Objekt enthält die folgenden Eigenschaften:
screens
: Ein Array vonScreenDetailed
Objekten, wobei jedes detaillierte Informationen über einen separaten Bildschirm enthält, der dem System zur Verfügung steht (siehe unten). Dieses Array ist auch nützlich, um die Anzahl der verfügbaren Bildschirme überscreens.length
zu bestimmen.currentScreen
: Ein einzelnesScreenDetailed
Objekt, das detaillierte Informationen über den Bildschirm enthält, auf dem das aktuelle Browserfenster angezeigt wird.
ScreenDetailed
Objekte erben die Eigenschaften der Screen
Schnittstelle und enthalten nützliche Informationen, um Fenster auf spezifischen Bildschirmen zu platzieren.
Hinweis: Sie können die Funktionalität basierend darauf beschränken, ob dem Nutzer mehr als ein Bildschirm zur Verfügung steht, indem Sie die Window.screen.isExtended
Eigenschaft verwenden. Diese gibt true
zurück, wenn das Gerät mehrere Bildschirme hat, und false
, wenn nicht.
Fenster öffnen
Sie müssen weiterhin Window.open()
verwenden, um Fenster zu öffnen und zu verwalten, aber das Obige bietet Ihnen bessere Informationen, um dies in einer Multi-Screen-Umgebung zu tun. Beispielsweise könnte eine Hilfsfunktion so aussehen:
// Array to hold references to the currently open windows
let windowRefs = [];
// ...
function openWindow(left, top, width, height, url) {
const windowFeatures = `left=${left},top=${top},width=${width},height=${height}`;
const windowRef = window.open(
url,
"_blank", // needed for it to open in a new window
windowFeatures,
);
if (windowRef === null) {
// If the browser is blocking new windows, close any windows that were
// able to open and display instructions to help the user fix this problem
closeAllWindows();
popoverElem.showPopover();
} else {
// Store a reference to the window in the windowRefs array
windowRefs.push(windowRef);
}
}
Sie würden diese Funktion dann aufrufen und Fenster auf spezifischen Bildschirmen wie folgt öffnen:
const screen1 = screenDetails.screens[0];
const screen2 = screenDetails.screens[1];
// Windows will be a third the width and the full height of the screen
// The available width of screen1, minus 3 times the horizontal browser chrome
// width, divided by 3
const windowWidth = Math.floor((screen1.availWidth - 3 * WINDOW_CHROME_X) / 3);
// The available height of screen1, minus the vertical browser chrome width
const windowHeight = Math.floor(screen1.availHeight - WINDOW_CHROME_Y);
// Open a window a third of the width and the entire height of the primary screen
openWindow(
screen1.availLeft,
screen1.availTop,
windowWidth,
windowHeight,
sites[1].url,
);
// ...
Alle Fenster schließen
Nach dem Öffnen jedes Fensters fügen wir eine Referenz auf das windowRefs
Array hinzu. Dies ermöglicht es Ihnen beispielsweise, sie alle zu schließen, wenn ein Fenster geschlossen wird:
function closeAllWindows() {
// Loop through all window refs and close each one
windowRefs.forEach((windowRef) => {
windowRef.close();
});
windowRefs = [];
}
// Check whether one of our popup windows has been closed
// If so, close them all
closeMonitor = setInterval(checkWindowClose, 250);
function checkWindowClose() {
if (windowRefs.some((windowRef) => windowRef.closed)) {
closeAllWindows();
clearInterval(closeMonitor);
}
}
Hinweis: In unseren Experimenten schien die oben gezeigte setInterval()
Polling-Methode am besten zum Erkennen des Schließens von Fenstern im Fall von mehreren Fenstern zu funktionieren. Die Verwendung von Ereignissen wie beforeunload
, pagehide
oder visibilitychange
erwies sich als unzuverlässig, da beim gleichzeitigen Öffnen mehrerer Fenster der schnelle Wechsel des Fokus/der Sichtbarkeit die Handlerfunktion verfrüht auslöste.
Hinweis: Ein Problem mit dem obigen Beispiel ist, dass es konstante Werte verwendet, um die Größe der Chrome-Fenster-UI-Teile in den Berechnungen darzustellen — WINDOW_CHROME_X
und WINDOW_CHROME_Y
— um die Fenstergrößenberechnungen korrekt zu erhalten. Um präzise dimensionierte Fenster in anderen zukünftigen Implementierungen der API zu erstellen, müssten Sie eine kleine Bibliothek von Browser-Chrome-Größen führen und eine Browser-Erkennung nutzen, um zu entdecken, welcher Browser Ihre App rendert, und die richtige Größe für die Berechnungen wählen. Oder Sie können sich auf weniger präzise Fenstergößen verlassen.
Umgang mit Browser-Popup-Blockern
In modernen Browsern ist für jeden Window.open()
Aufruf ein separates Benutzer-Gestenevent erforderlich, aus Sicherheitsgründen. Dies verhindert, dass Seiten die Nutzer mit vielen Fenstern überfluten. Allerdings stellt dies ein Problem für Multi-Window-Anwendungen dar. Um diese Einschränkung zu umgehen, können Sie Ihre Anwendungen so gestalten, dass:
- Nicht mehr als ein neues Fenster gleichzeitig geöffnet wird.
- Bestehende Fenster wiederverwendet werden, um verschiedene Seiten anzuzeigen.
- Nutzer darüber informiert werden, wie sie ihre Browsereinstellungen aktualisieren können, um mehrere Fenster zuzulassen.
In unserer Demo-Anwendung haben wir uns für die dritte Option entschieden. Unsere openWindow()
Funktion enthält den folgenden Abschnitt:
// ...
if (windowRef === null) {
// If the browser is blocking new windows, close any windows that were
// able to open and display instructions to help the user fix this problem
closeAllWindows();
popoverElem.showPopover();
} else {
// Store a reference to the window in the windowRefs array
windowRefs.push(windowRef);
}
// ...
Wenn der Browser ein neues Fenster blockiert, wird das resultierende windowRef
null
sein. In diesem Fall führen wir unsere closeAllWindows()
Funktion aus, um alle Fenster zu schließen, die geöffnet wurden, bevor das Blockieren begann, und zeigen ein Popover-Element an, das erklärt, wie der Popup-Blocker deaktiviert werden kann.
Einfacher Fall mit einem Fenster pro Anzeigegerät
Wenn Sie ein einzelnes Fenster auf jedem verfügbaren Anzeigegerät öffnen möchten, das die volle Breite und Höhe des Displays hat, könnten Sie ein Muster wie dieses verwenden:
// Open a window on each screen of the device
for (const screen of screenDetails.screens) {
openWindow(
screen.availLeft,
screen.availTop,
screen.availWidth,
screen.availHeight,
url,
);
}
Window-Management-Ereignisse
Die Window Management API bietet einige Ereignisse, um auf Änderungen der verfügbaren Bildschirme zu reagieren:
- Das
ScreenDetails
screenschange
Ereignis -
Wird ausgelöst, wenn Bildschirme mit dem System verbunden oder davon getrennt werden.
- Das
ScreenDetails
currentscreenchange
Ereignis -
Wird ausgelöst, wenn der aktuelle Bildschirm des Fensters sich in irgendeiner Weise ändert.
- Das
Screen
change
Ereignis -
Wird auf einem spezifischen Bildschirm ausgelöst, wenn sich dieser in irgendeiner Weise ändert.
So könnten Sie beispielsweise das screenschange
Ereignis verwenden, um zu erkennen, wenn sich die verfügbaren Bildschirme geändert haben (vielleicht wenn ein Bildschirm angeschlossen oder abgesteckt wird), die Änderung melden, alle Fenster schließen und die Fensteranordnungen an die neue Konfiguration anpassen:
screenDetails.addEventListener("screenschange", () => {
// If the new number of screens is different to the old number of screens,
// report the difference
if (screenDetails.screens.length !== noOfScreens) {
console.log(
`The screen count changed from ${noOfScreens} to ${screenDetails.screens.length}`,
);
}
// If the windows are open, close them and then open them again
// So that they fit with the new screen configuration
if (windowRefs.length > 0) {
closeAllWindows();
openWindows();
}
});
requestFullscreen() Bildschirmoption
Die Window Management API fügt eine neue screen
Option zur requestFullscreen()
Methode hinzu, mit der Sie festlegen können, auf welchem Bildschirm Sie das Element im Vollbildmodus anzeigen möchten. Wenn Sie beispielsweise das Vollbild auf dem primären Betriebssystem-Bildschirm anzeigen möchten:
try {
const primaryScreen = (await getScreenDetails()).screens.find(
(screen) => screen.isPrimary,
);
await document.body.requestFullscreen({ screen: primaryScreen });
} catch (err) {
console.error(err.name, err.message);
}