Nhận thông tin về màn hình được kết nối và vị trí của cửa sổ so với các màn hình đó.
Window Management API
Window Management API cho phép bạn liệt kê các màn hình được kết nối với máy và đặt cửa sổ trên các màn hình cụ thể.
Các trường hợp sử dụng được đề xuất
Sau đây là ví dụ về các trang web có thể sử dụng API này:
- Trình chỉnh sửa đồ hoạ nhiều cửa sổ như Gimp có thể đặt nhiều công cụ chỉnh sửa trong các cửa sổ được định vị chính xác.
- Các bộ phận chuyên trách giao dịch ảo có thể cho thấy xu hướng thị trường qua nhiều cửa sổ, bạn có thể xem bất kỳ cửa sổ nào ở chế độ toàn màn hình.
- Ứng dụng trình chiếu có thể hiển thị ghi chú của người thuyết trình trên màn hình chính bên trong và bản trình bày trên máy chiếu bên ngoài.
Cách sử dụng API Quản lý cửa sổ
Vấn đề
Phương pháp kiểm thử thời gian để kiểm soát cửa sổ, Window.open()
, đáng tiếc là không nhận biết được các màn hình bổ sung. Mặc dù một số khía cạnh của API này có vẻ hơi cổ xưa, chẳng hạn như tham số windowFeatures
DOMString
, nhưng API này vẫn phục vụ chúng ta rất tốt trong nhiều năm qua. Để chỉ định vị trí của cửa sổ, bạn có thể truyền toạ độ dưới dạng left
và top
(hoặc screenX
và screenY
tương ứng) và truyền kích thước mong muốn dưới dạng width
và height
(hoặc innerWidth
và innerHeight
tương ứng). Ví dụ: để mở cửa sổ 400x300 ở 50 pixel từ bên trái và 50 pixel từ trên cùng, bạn có thể sử dụng mã sau:
const popup = window.open(
'https://example.com/',
'My Popup',
'left=50,top=50,width=400,height=300',
);
Bạn có thể lấy thông tin về màn hình hiện tại bằng cách xem thuộc tính window.screen
. Thuộc tính này sẽ trả về một đối tượng Screen
. Đây là đầu ra trên MacBook Pro 13 inch của tôi:
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
*/
Giống như hầu hết những người làm việc trong ngành công nghệ, tôi đã phải thích ứng với thực tế công việc mới và thiết lập văn phòng cá nhân tại nhà. Cấu hình của tôi như trong ảnh bên dưới (nếu quan tâm, bạn có thể đọc thông tin chi tiết đầy đủ về cách thiết lập của tôi). iPad bên cạnh MacBook được kết nối với máy tính xách tay thông qua Sidecar. Vì vậy, bất cứ khi nào cần, tôi có thể nhanh chóng biến iPad thành màn hình thứ hai.
Nếu muốn tận dụng màn hình lớn hơn, tôi có thể đặt cửa sổ bật lên từ mã mẫu ở trên vào màn hình thứ hai. Tôi thực hiện như sau:
popup.moveTo(2500, 50);
Đây là một dự đoán gần đúng vì không có cách nào để biết kích thước của màn hình thứ hai. Thông tin từ window.screen
chỉ bao gồm màn hình tích hợp, chứ không bao gồm màn hình iPad. width
được báo cáo của màn hình tích hợp là 1680
pixel, vì vậy, việc chuyển sang 2500
pixel có thể giúp chuyển cửa sổ sang iPad, vì tôi tình cờ biết rằng cửa sổ đó nằm ở bên phải MacBook. Làm cách nào để thực hiện việc này trong trường hợp chung? Hóa ra, có một cách tốt hơn là đoán. Đó là API Quản lý cửa sổ.
Phát hiện tính năng
Để kiểm tra xem Window Management API có được hỗ trợ hay không, hãy sử dụng:
if ('getScreenDetails' in window) {
// The Window Management API is supported.
}
Quyền window-management
Trước khi có thể sử dụng API Quản lý cửa sổ, tôi phải yêu cầu người dùng cấp quyền làm việc đó.
Bạn có thể truy vấn quyền window-management
bằng
API Quyền như sau:
let granted = false;
try {
const { state } = await navigator.permissions.query({ name: 'window-management' });
granted = state === 'granted';
} catch {
// Nothing.
}
Mặc dù các trình duyệt có tên quyền cũ và tên quyền mới đang được sử dụng, hãy nhớ sử dụng mã phòng vệ khi yêu cầu quyền, như trong ví dụ dưới đây.
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;
});
Trình duyệt có thể chọn hiển thị lời nhắc cấp quyền một cách linh động trong lần đầu tiên cố gắng sử dụng bất kỳ phương thức nào của API mới. Hãy đọc tiếp để tìm hiểu thêm.
Thuộc tính window.screen.isExtended
Để tìm hiểu xem có nhiều màn hình được kết nối với thiết bị của tôi hay không, tôi truy cập vào thuộc tính window.screen.isExtended
. Phương thức này sẽ trả về true
hoặc false
. Đối với chế độ thiết lập của tôi, hệ thống sẽ trả về true
.
window.screen.isExtended;
// Returns `true` or `false`.
Phương thức getScreenDetails()
Bây giờ, tôi biết rằng chế độ thiết lập hiện tại là nhiều màn hình, tôi có thể lấy thêm thông tin về màn hình thứ hai bằng Window.getScreenDetails()
. Việc gọi hàm này sẽ hiển thị lời nhắc cấp quyền hỏi xem trang web có thể mở và đặt cửa sổ trên màn hình của tôi hay không. Hàm này trả về một lời hứa giải quyết bằng đối tượng ScreenDetailed
. Trên MacBook Pro 13 có một iPad được kết nối, trường này bao gồm trường screens
có 2 đối tượng 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
}]
}
*/
Thông tin về các màn hình đã kết nối có trong mảng screens
. Hãy lưu ý cách giá trị của left
cho iPad bắt đầu từ 1680
, chính xác là width
của màn hình tích hợp. Điều này cho phép tôi xác định chính xác cách các màn hình được sắp xếp hợp lý (cạnh nhau, chồng lên nhau, v.v.). Hiện tại, mỗi màn hình cũng có dữ liệu cho biết màn hình đó có phải là màn hình isInternal
hay không và có phải là màn hình isPrimary
hay không. Xin lưu ý rằng màn hình tích hợp không nhất thiết phải là màn hình chính.
Trường currentScreen
là một đối tượng trực tiếp tương ứng với window.screen
hiện tại. Đối tượng được cập nhật trên các vị trí của cửa sổ trên nhiều màn hình hoặc các thay đổi về thiết bị.
Sự kiện screenschange
Hiện tại, điều duy nhất còn thiếu là cách phát hiện thời điểm chế độ thiết lập màn hình của tôi thay đổi. Một sự kiện mới, screenschange
, thực hiện chính xác việc đó: sự kiện này sẽ kích hoạt bất cứ khi nào bạn sửa đổi cụm sao màn hình. (Lưu ý rằng "màn hình" ở dạng số nhiều trong tên sự kiện.) Điều này có nghĩa là sự kiện sẽ kích hoạt bất cứ khi nào màn hình mới hoặc màn hình hiện có (về mặt vật lý hoặc ảo trong trường hợp Sidecar) được cắm hoặc rút phích cắm.
Xin lưu ý rằng bạn cần tra cứu thông tin chi tiết về màn hình mới một cách không đồng bộ, chính sự kiện screenschange
không cung cấp dữ liệu này. Để tra cứu thông tin chi tiết về màn hình, hãy sử dụng đối tượng trực tiếp từ giao diện Screens
đã lưu vào bộ nhớ đệm.
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;
}
});
Sự kiện currentscreenchange
Nếu chỉ quan tâm đến các thay đổi đối với màn hình hiện tại (tức là giá trị của đối tượng trực tiếp currentScreen
), tôi có thể theo dõi sự kiện currentscreenchange
.
const screenDetails = await window.getScreenDetails();
screenDetails.addEventListener('currentscreenchange', async (event) => {
const details = screenDetails.currentScreen;
console.log('The current screen has changed.', event, details);
});
Sự kiện change
Cuối cùng, nếu chỉ quan tâm đến các thay đổi đối với một màn hình cụ thể, tôi có thể nghe sự kiện change
của màn hình đó.
const firstScreen = (await window.getScreenDetails())[0];
firstScreen.addEventListener('change', async (event) => {
console.log('The first screen has changed.', event, firstScreen);
});
Tuỳ chọn mới cho chế độ toàn màn hình
Cho đến thời điểm này, bạn có thể yêu cầu các phần tử hiển thị ở chế độ toàn màn hình thông qua phương thức requestFullScreen()
được đặt tên phù hợp. Phương thức này sẽ lấy một tham số options
mà bạn có thể truyền FullscreenOptions
. Cho đến nay, thuộc tính duy nhất của lớp này là navigationUI
.
API Quản lý cửa sổ thêm một thuộc tính screen
mới cho phép bạn xác định màn hình để bắt đầu chế độ xem toàn màn hình. Ví dụ: nếu bạn muốn đặt màn hình chính ở chế độ toàn màn hình:
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);
}
Polyfill
Bạn không thể polyfill API Quản lý cửa sổ, nhưng bạn có thể tạo hình dạng của API này để có thể lập trình riêng cho API mới:
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;
}
Các khía cạnh khác của API, tức là nhiều sự kiện thay đổi màn hình và thuộc tính screen
của FullscreenOptions
, sẽ không bao giờ kích hoạt hoặc bị các trình duyệt không hỗ trợ bỏ qua tương ứng.
Bản minh hoạ
Nếu giống tôi, bạn sẽ theo dõi chặt chẽ sự phát triển của nhiều loại tiền mã hoá. (Thực tế thì tôi không muốn điều đó vì tôi yêu hành tinh này, nhưng để cho bài viết này được trọn vẹn, hãy giả sử tôi muốn điều đó.) Để theo dõi các loại tiền mã hoá mà mình sở hữu, tôi đã phát triển một ứng dụng web cho phép tôi xem thị trường trong mọi tình huống trong cuộc sống, chẳng hạn như ngay trên giường, nơi tôi có thiết lập một màn hình hợp lý.
Vì đây là thị trường tiền mã hoá nên mọi thứ có thể trở nên hỗn loạn bất cứ lúc nào. Nếu điều này xảy ra, tôi có thể nhanh chóng di chuyển đến bàn làm việc nơi tôi có thiết lập nhiều màn hình. Tôi có thể nhấp vào cửa sổ của một đơn vị tiền tệ bất kỳ và nhanh chóng xem toàn bộ thông tin chi tiết ở chế độ xem toàn màn hình trên màn hình đối diện. Dưới đây là ảnh tôi chụp gần đây trong lần tắm máu tại YCY vừa qua. Nó làm tôi hoàn toàn mất cảnh giác và để tôi đặt tay lên mặt.
Bạn có thể phát với bản minh hoạ được nhúng bên dưới hoặc xem mã nguồn của bản minh hoạ bị lỗi.
Tính bảo mật và quyền truy cập
Nhóm Chrome đã thiết kế và triển khai API Quản lý cửa sổ bằng cách sử dụng các nguyên tắc cốt lõi được xác định trong phần Kiểm soát quyền truy cập vào các tính năng mạnh mẽ của nền tảng web, bao gồm cả quyền kiểm soát của người dùng, tính minh bạch và tính công thái học. API Quản lý cửa sổ hiển thị thông tin mới về các màn hình được kết nối với một thiết bị, tăng diện tích vân tay của người dùng, đặc biệt là những người dùng có nhiều màn hình được kết nối liên tục với thiết bị của họ. Để giảm thiểu mối lo ngại về quyền riêng tư này, các thuộc tính màn hình hiển thị được giới hạn ở mức tối thiểu cần thiết cho các trường hợp sử dụng vị trí phổ biến. Các trang web cần có quyền của người dùng để nhận thông tin nhiều màn hình và đặt cửa sổ trên các màn hình khác. Mặc dù Chromium trả về nhãn màn hình chi tiết, nhưng trình duyệt có thể trả về nhãn ít mô tả hơn (hoặc thậm chí là nhãn trống).
Quyền kiểm soát của người dùng
Người dùng có toàn quyền kiểm soát mức độ hiển thị của chế độ thiết lập. Người dùng có thể chấp nhận hoặc từ chối lời nhắc cấp quyền và thu hồi quyền đã cấp trước đó thông qua tính năng thông tin trang web trong trình duyệt.
Kiểm soát doanh nghiệp
Người dùng Chrome Enterprise có thể kiểm soát một số khía cạnh của API Quản lý cửa sổ như được nêu trong phần liên quan của chế độ cài đặt Nhóm chính sách nguyên tử.
Sự minh bạch
Việc quyền sử dụng API Quản lý cửa sổ đã được cấp hay chưa sẽ được hiển thị trong thông tin trang web của trình duyệt và cũng có thể được truy vấn thông qua API Quyền.
Quyền ổn định
Trình duyệt vẫn duy trì các quyền được cấp. Bạn có thể thu hồi quyền này thông qua thông tin trang web của trình duyệt.
Phản hồi
Nhóm Chrome muốn biết trải nghiệm của bạn với Window Management API.
Giới thiệu cho chúng tôi về thiết kế API
API có hoạt động như mong đợi không? Hay có phương thức hoặc thuộc tính nào bị thiếu mà bạn cần để triển khai ý tưởng của mình không? Bạn có câu hỏi hoặc nhận xét về mô hình bảo mật không?
- Gửi vấn đề về thông số kỹ thuật trên kho lưu trữ GitHub tương ứng hoặc thêm ý kiến của bạn vào một vấn đề hiện có.
Báo cáo vấn đề về việc triển khai
Bạn có phát hiện lỗi khi triển khai Chrome không? Hay cách triển khai có khác với thông số kỹ thuật không?
- Gửi lỗi tại new.crbug.com. Hãy nhớ cung cấp nhiều thông tin chi tiết nhất có thể, các hướng dẫn đơn giản để tái tạo và nhập
Blink>Screen>MultiScreen
vào hộp Thành phần. Glitch rất hữu ích khi chia sẻ các bản dựng lại nhanh chóng và dễ dàng.
Hỗ trợ API
Bạn có dự định sử dụng API Quản lý cửa sổ không? Sự ủng hộ công khai của bạn giúp nhóm Chrome ưu tiên các tính năng và cho các nhà cung cấp trình duyệt khác thấy tầm quan trọng của việc hỗ trợ các tính năng đó.
- Hãy chia sẻ cách bạn dự định sử dụng công cụ này trên luồng thảo luận Discourse của WICG.
- Gửi một tweet đến @ChromiumDev bằng hashtag
#WindowManagement
và cho chúng tôi biết bạn đang sử dụng ở đâu và như thế nào. - Yêu cầu các nhà cung cấp trình duyệt khác triển khai API.
Các đường liên kết hữu ích
- Bản nháp quy cách
- Thông báo giải thích công khai
- Bản minh hoạ Window Management API | Nguồn bản minh hoạ Window Management API
- Lỗi theo dõi Chromium
- Mục ChromeStatus.com
- Thành phần nhấp nháy:
Blink>Screen>MultiScreen
- Xem xét thẻ
- Ý định thử nghiệm
Xác nhận
Thông số kỹ thuật của API Quản lý cửa sổ do Victor Costan, Joshua Bell và Mike Wasserman chỉnh sửa. API này do Mike Wasserman và Adrienne Walker triển khai. Bài viết này đã được Joe Medley, François Beaufort và Kayce Basques xem xét. Cảm ơn Laura Torrent Puig đã cung cấp ảnh.