uzyskiwać informacje o podłączonych wyświetlaczach i oknach w stosunku do tych wyświetlaczy;
Window Management API
Interfejs Window Management API umożliwia zliczanie wyświetlaczy połączonych z urządzeniem oraz umieszczanie okien na określonych ekranach.
Sugerowane zastosowania
Przykłady witryn, które mogą korzystać z tego interfejsu API:
- Edytory grafiki z wieloma oknami w stylu Gimp mogą umieszczać różne narzędzia do edycji w precyzyjnie rozmieszczonych oknach.
- Wirtualne biura transakcyjne mogą wyświetlać trendy rynkowe w wielu oknach, z których każde można wyświetlić w trybie pełnoekranowym.
- Aplikacje do pokazów slajdów mogą wyświetlać notatki na wewnętrznym ekranie głównym, a prezentację na zewnętrznym projektorze.
Jak korzystać z interfejsu Window Management API
Problem
Sprawdzona metoda sterowania oknamiWindow.open()
nie uwzględnia niestety dodatkowych ekranów. Chociaż niektóre aspekty tego interfejsu API wydają się nieco przestarzałe, np. parametr windowFeatures
DOMString
, to przez lata dobrze nam służył. Aby określić położenie okna, możesz przekazać współrzędne jako left
i top
(odpowiednio screenX
i screenY
) oraz przekazać żądany rozmiar jako width
i height
(odpowiednio innerWidth
i innerHeight
). Jeśli na przykład chcesz otworzyć okno o wymiarach 400 × 300 w odległości 50 pikseli od lewej i 50 pikseli od góry, możesz użyć tego kodu:
const popup = window.open(
'https://example.com/',
'My Popup',
'left=50,top=50,width=400,height=300',
);
Informacje o bieżącym ekranie możesz uzyskać, korzystając z właściwości window.screen
, która zwraca obiekt Screen
. Oto wynik na moim MacBooku Pro 13″:
window.screen;
/* Output from my MacBook Pro 13″:
availHeight: 969
availLeft: 0
availTop: 25
availWidth: 1680
colorDepth: 30
height: 1050
isExtended: true
onchange: null
orientation: ScreenOrientation {angle: 0, type: "landscape-primary", onchange: null}
pixelDepth: 30
width: 1680
*/
Podobnie jak większość osób pracujących w branży technologicznej musiałem dostosować się do nowej rzeczywistości i urządzić sobie domowe biuro. Mój wygląda tak jak na zdjęciu poniżej (jeśli chcesz, możesz przeczytać szczegóły dotyczące mojego konfiguracji). iPad obok MacBooka jest połączony z laptopem przez Sidecar, więc w razie potrzeby mogę szybko przekształcić iPada w drugi ekran.
Jeśli chcę skorzystać z większego ekranu, mogę umieścić wyskakujące okienko z przykładowego kodu powyżej na drugim ekranie. Robię to tak:
popup.moveTo(2500, 50);
Jest to przybliżony szacunek, ponieważ nie ma możliwości określenia wymiarów drugiego ekranu. Informacje z window.screen
dotyczą tylko wbudowanego ekranu, a nie ekranu iPada. Raportowany width
ekranu wbudowanego urządzenia to 1680
pikseli, więc przeniesienie do 2500
pikseli może pomóc w przesunięciu okna na iPada, ponieważ wiem, że znajduje się on po prawej stronie mojego MacBooka. Jak mogę to zrobić w ogóle? Okazuje się, że istnieje lepszy sposób niż zgadywanie. Jest to interfejs Window Management API.
Wykrywanie cech
Aby sprawdzić, czy interfejs Window Management API jest obsługiwany, użyj:
if ('getScreenDetails' in window) {
// The Window Management API is supported.
}
Uprawnienie window-management
Zanim użyję interfejsu Window Management API, muszę poprosić użytkownika o pozwolenie. Uprawnienie window-management
można zapytać za pomocą interfejsu Permissions API w ten sposób:
let granted = false;
try {
const { state } = await navigator.permissions.query({ name: 'window-management' });
granted = state === 'granted';
} catch {
// Nothing.
}
Podczas korzystania z przeglądarek z uprawnieniami o starej i nowej nazwie pamiętaj, aby podczas prośby o uprawnienia używać kodu obronnego, jak w przykładzie poniżej.
async function getWindowManagementPermissionState() {
let state;
// The new permission name.
try {
({ state } = await navigator.permissions.query({
name: "window-management",
}));
} catch (err) {
return `${err.name}: ${err.message}`;
}
return state;
}
document.querySelector("button").addEventListener("click", async () => {
const state = await getWindowManagementPermissionState();
document.querySelector("pre").textContent = state;
});
Przeglądarka może wyświetlić prośbę o uprawnienia dynamicznie przy pierwszej próbie użycia dowolnej metody nowego interfejsu API. Aby dowiedzieć się więcej, czytaj dalej.
Właściwość window.screen.isExtended
Aby sprawdzić, czy do mojego urządzenia jest podłączonych więcej niż 1 ekran, otwieram usługę window.screen.isExtended
. Zwraca wartość true
lub false
. W moim przypadku zwraca on wartość true
.
window.screen.isExtended;
// Returns `true` or `false`.
Metoda getScreenDetails()
Teraz, gdy wiem, że bieżąca konfiguracja to konfiguracja wieloekranowa, mogę uzyskać więcej informacji o drugim ekranie, używając Window.getScreenDetails()
. Po wywołaniu tej funkcji wyświetli się prośba o uprawnienia, w której pytam, czy witryna może otwierać i umieszczać okna na moim ekranie. Funkcja zwraca obietnicę, która zwraca obiekt ScreenDetailed
. Na moim MacBooku Pro 13 z podłączonym iPadem obejmuje to pole screens
z 2 obiektmi ScreenDetailed
:
await window.getScreenDetails();
/* Output from my MacBook Pro 13″ with the iPad attached:
{
currentScreen: ScreenDetailed {left: 0, top: 0, isPrimary: true, isInternal: true, devicePixelRatio: 2, …}
oncurrentscreenchange: null
onscreenschange: null
screens: [{
// The MacBook Pro
availHeight: 969
availLeft: 0
availTop: 25
availWidth: 1680
colorDepth: 30
devicePixelRatio: 2
height: 1050
isExtended: true
isInternal: true
isPrimary: true
label: "Built-in Retina Display"
left: 0
onchange: null
orientation: ScreenOrientation {angle: 0, type: "landscape-primary", onchange: null}
pixelDepth: 30
top: 0
width: 1680
},
{
// The iPad
availHeight: 999
availLeft: 1680
availTop: 25
availWidth: 1366
colorDepth: 24
devicePixelRatio: 2
height: 1024
isExtended: true
isInternal: false
isPrimary: false
label: "Sidecar Display (AirPlay)"
left: 1680
onchange: null
orientation: ScreenOrientation {angle: 0, type: "landscape-primary", onchange: null}
pixelDepth: 24
top: 0
width: 1366
}]
}
*/
Informacje o połączonych ekranach są dostępne w tablicy screens
. Zwróć uwagę, że wartość left
dla iPada zaczyna się od 1680
, co odpowiada dokładnie width
wbudowanego wyświetlacza. Pozwala mi to określić, jak dokładnie ekrany są logicznie rozmieszczone (obok siebie, jeden na drugim itp.). W przypadku każdego ekranu są też dane określające, czy jest to ekran isInternal
czy isPrimary
. Pamiętaj, że wbudowany ekran niekoniecznie jest ekranem głównym.
Pole currentScreen
to aktywny obiekt odpowiadający bieżącemu window.screen
. Obiekt jest aktualizowany w przypadku umieszczenia okna na różnych ekranach lub zmiany urządzenia.
Zdarzenie screenschange
Jedyną rzeczą, której brakuje, jest sposób wykrywania zmian w układzie ekranu. Nowe zdarzenie screenschange
działa właśnie w ten sposób: jest wywoływane, gdy nastąpi zmiana konstelacji ekranu. (Zwróć uwagę, że w nazwie zdarzenia „screens” występuje w formie liczby mnogiej.) Oznacza to, że zdarzenie jest wywoływane za każdym razem, gdy nowy lub istniejący ekran jest podłączany lub odłączany (fizycznie lub wirtualnie w przypadku Sidecar).
Pamiętaj, że informacje o nowym ekranie musisz wyszukiwać asynchronicznie, ponieważ zdarzenie screenschange
samo w sobie nie zawiera tych danych. Aby sprawdzić szczegóły ekranu, użyj obiektu na żywo z interfejsu z pamięci podręcznejScreens
.
const screenDetails = await window.getScreenDetails();
let cachedScreensLength = screenDetails.screens.length;
screenDetails.addEventListener('screenschange', (event) => {
if (screenDetails.screens.length !== cachedScreensLength) {
console.log(
`The screen count changed from ${cachedScreensLength} to ${screenDetails.screens.length}`,
);
cachedScreensLength = screenDetails.screens.length;
}
});
Zdarzenie currentscreenchange
Jeśli interesują mnie tylko zmiany na bieżącym ekranie (czyli wartość obiektu na żywocurrentScreen
), mogę nasłuchiwać zdarzenia currentscreenchange
.
const screenDetails = await window.getScreenDetails();
screenDetails.addEventListener('currentscreenchange', async (event) => {
const details = screenDetails.currentScreen;
console.log('The current screen has changed.', event, details);
});
Zdarzenie change
Jeśli interesują mnie tylko zmiany na konkretnym ekranie, mogę odsłuchać zdarzenie change
tego ekranu.
const firstScreen = (await window.getScreenDetails())[0];
firstScreen.addEventListener('change', async (event) => {
console.log('The first screen has changed.', event, firstScreen);
});
Nowe opcje pełnego ekranu
Do tej pory można było poprosić o wyświetlanie elementów w trybie pełnoekranowym za pomocą odpowiedniej metody requestFullScreen()
. Metoda przyjmuje parametr options
, do którego możesz przekazać wartość FullscreenOptions
. Do tej pory jego jedyną usługą była usługa navigationUI
.
Interfejs Window Management API dodaje nową właściwość screen
, która pozwala określić, na którym ekranie ma się rozpocząć widok pełnoekranowy. Jeśli na przykład chcesz wyświetlić ekran główny na pełnym ekranie:
try {
const primaryScreen = (await getScreenDetails()).screens.filter((screen) => screen.isPrimary)[0];
await document.body.requestFullscreen({ screen: primaryScreen });
} catch (err) {
console.error(err.name, err.message);
}
Watolina
Nie można polyfillować interfejsu Window Management API, ale możesz użyć szablonu, aby móc kodować wyłącznie w nowym interfejsie API:
if (!('getScreenDetails' in window)) {
// Returning a one-element array with the current screen,
// noting that there might be more.
window.getScreenDetails = async () => [window.screen];
// Set to `false`, noting that this might be a lie.
window.screen.isExtended = false;
}
Inne aspekty interfejsu API, czyli różne zdarzenia zmiany ekranu i właściwość screen
obiektu FullscreenOptions
, nie byłyby w ogóle wywoływane lub byłyby ignorowane przez przeglądarki, które nie obsługują tej funkcji.
Prezentacja
Jeśli jesteś podobny do mnie, na pewno uważnie śledzisz rozwój różnych kryptowalut. (W rzeczywistości nie chcę tego robić, ponieważ kocham tę planetę, ale na potrzeby tego artykułu załóżmy, że tak jest). Aby śledzić swoje kryptowaluty, stworzyłem aplikację internetową, która pozwala mi obserwować rynki w każdej sytuacji życiowej, na przykład z wygody łóżka, gdzie mam przyzwoite ustawienie z jednym ekranem.
W przypadku kryptowalut sytuacja na rynkach może się w każdej chwili zmienić. W takiej sytuacji mogę szybko przejść do mojego biurka, gdzie mam konfigurację z wieloma ekranami. Mogę kliknąć okno dowolnej waluty i szybko wyświetlić pełne szczegóły w widoku pełnoekranowym na drugim ekranie. Poniżej znajduje się moje zdjęcie zrobione podczas ostatniej krwawej bitwy YCY. Złapał mnie całkowicie nieprzygotowanego i umieścił moje ręce na twarzy.
Możesz wypróbować demo umieszczone poniżej lub sprawdzić kod źródłowy na stronie glitch.
Zabezpieczenia i uprawnienia
Zespół Chrome zaprojektował i wdrożył interfejs Window Management API, korzystając z podstawowych zasad określonych w artykule Controlling Access to Powerful Web Platform Features (Zarządzanie dostępem do zaawansowanych funkcji platformy internetowej), w tym kontroli użytkownika, przejrzystości i ergonomiki. Interfejs Window Management API udostępnia nowe informacje o ekranach połączonych z urządzeniem, co zwiększa powierzchnię odcisku palca użytkowników, zwłaszcza tych, którzy mają wiele ekranów stale połączonych ze swoimi urządzeniami. Aby rozwiązać ten problem, ograniczyliśmy liczbę wyświetlanych właściwości ekranu do minimum potrzebnego w najczęstszych przypadkach użycia. Aby witryny mogły uzyskiwać informacje o wielu ekranach i rozmieszczać okna na innych ekranach, muszą mieć na to zgodę użytkownika. Podczas gdy Chromium zwraca szczegółowe etykiety ekranu, inne przeglądarki mogą zwracać mniej opisowe (lub nawet puste) etykiety.
Kontrola użytkownika
Użytkownik ma pełną kontrolę nad ekspozycją swojego urządzenia. Mogą zaakceptować lub odrzucić prośbę o zgodę i cofnąć wcześniej udzieloną zgodę za pomocą funkcji informacji o witrynie w przeglądarce.
Kontrola firmowa
Użytkownicy Chrome Enterprise mogą kontrolować kilka aspektów interfejsu Window Management API, jak opisano w odpowiedniej sekcji ustawień Atomicznych grup zasad.
Przejrzystość
Informacje o tym, czy użytkownik zezwolił na korzystanie z interfejsu Window Management API, są dostępne w informacjach o witrynie w przeglądarce. Można je też uzyskać za pomocą interfejsu Permissions API.
Trwałość uprawnień
Przeglądarka zachowuje przyznane uprawnienia. Użytkownik może cofnąć zgodę w informacjach o witrynie przeglądarki.
Prześlij opinię
Zespół Chrome chce poznać Twoje wrażenia z korzystania z interfejsu Window Management API.
Poinformuj nas o projektowaniu interfejsu API
Czy coś w interfejsie API nie działa zgodnie z oczekiwaniami? A może brakuje metod lub właściwości, których potrzebujesz do wdrożenia swojego pomysłu? Masz pytania lub uwagi dotyczące modelu bezpieczeństwa?
- Zgłoś problem ze specyfikacją w odpowiednim repozytorium GitHub lub dodaj swoje uwagi do istniejącego problemu.
Zgłaszanie problemów z implementacją
Czy znalazłeś/znalazłaś błąd w implementacji Chrome? A może implementacja różni się od specyfikacji?
- Zgłoś błąd na stronie new.crbug.com. Podaj jak najwięcej szczegółów, proste instrukcje odtwarzania błędu i wpisz
Blink>Screen>MultiScreen
w polu Components. Glitch to świetne narzędzie do szybkiego i łatwego udostępniania informacji o powtarzających się problemach.
Pokaż informacje o pomocy dotyczącej interfejsu API
Zamierzasz używać interfejsu Window Management API? Twoja publiczna pomoc pomaga zespołowi Chrome ustalać priorytety funkcji i pokazuje innym dostawcom przeglądarek, jak ważne jest wspieranie tych funkcji.
- W wątku na forum Discourse WICG opisz, jak zamierzasz go używać.
- Wyślij tweeta do @ChromiumDev, używając hashtaga
#WindowManagement
, i podaj, gdzie i jak z niego korzystasz. - Poproś innych dostawców przeglądarek o wdrożenie interfejsu API.
Przydatne linki
- Specyfikacja w wersji roboczej
- Publiczny film wyjaśniający
- Demo interfejsu Window Management API | demo interfejsu Window Management API
- Błąd śledzenia w Chromium
- Wpis na stronie ChromeStatus.com
- Składnik Blink:
Blink>Screen>MultiScreen
- Sprawdzanie tagów
- Zamierzasz przeprowadzić eksperyment
Podziękowania
Specyfikację interfejsu Window Management API opracowali Victor Costan, Joshua Bell i Mike Wasserman. Interfejs API został wdrożony przez Mike’a Wassermana i Adrienne Walker. Ten artykuł został sprawdzony przez Joe Medley, François Beaufort i Kayce Basques. Dziękujemy Laurze Torrent Puig za zdjęcia.