Nhận thông tin về màn hình đã kết nối và định vị cửa sổ tương ứng với các màn hình đó.
API Quản lý cửa sổ
API Quản lý cửa sổ cho phép bạn liệt kê các màn hình được kết nối với máy của bạn 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
Ví dụ về các trang web có thể sử dụng API này bao gồm:
- Trình chỉnh sửa đồ hoạ nhiều cửa sổ à la Gimp có thể đặt nhiều vị trí vào các cửa sổ được đặt 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 trong số đó 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 nội bộ 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ử lâu dài để kiểm soát cửa sổ,
Rất tiếc, Window.open()
không biết về 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ũ, chẳng hạn như
windowFeatures
DOMString
, nhưng nền tảng này đã phục vụ chúng tôi tốt trong những năm qua. Để chỉ định
vị trí, bạn có thể chuyển hàm
có toạ độ dưới dạng left
và top
(hoặc screenX
và screenY
tương ứng) rồi chuyển giá trị mong muốn
size thành
width
và height
(hoặc innerWidth
và innerHeight
tương ứng). Ví dụ: để mở một
Cửa sổ 400 × 300 ở 50 pixel từ bên trái và 50 pixel từ trên cùng, đây là mã mà bạn
có thể sử dụng:
const popup = window.open(
'https://example.com/',
'My Popup',
'left=50,top=50,width=400,height=300',
);
Bạn có thể nhận thông tin về màn hình hiện tại bằng cách xem
Thuộc tính window.screen
sẽ trả về một đối tượng Screen
. Đây là
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ủa tôi trông giống như trên bức ảnh dưới đây (nếu bạn quan tâm, bạn có thể đọc toàn bộ thông tin chi tiết về cách thiết lập của tôi). iPad bên cạnh MacBook của tôi được kết nối với máy tính xách tay qua Sidecar, để bất cứ khi nào cần, tôi có thể nhanh chóng bật iPad vào 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 chuyển sang màn hình thứ hai. Tôi làm được như sau:
popup.moveTo(2500, 50);
Đây chỉ là phỏng đoán, 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ỉ che màn hình tích hợp chứ không che màn hình iPad. width
bị báo cáo
màn hình tích hợp là 1680
pixel, vì vậy việc di chuyển đến 2500
pixel có thể hiệu quả để chuyển
sang iPad, vì tôi biết rằng ứng dụng này nằm ở bên phải MacBook của mình. Cách thức
tôi có thể làm điều này đối với trường hợp chung không? Hoá ra vẫn có một cách hay hơn là đoán. Đó chính là
API Quản lý cửa sổ.
Phát hiện tính năng
Để kiểm tra xem API Quản lý cửa sổ 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ư vậy:
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 tự động hiển thị lời nhắc cấp quyền vào lần đầu tiên sử dụng bất kỳ phương thức nào 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
Thuộc tính window.screen.isExtended
. Hàm này trả về true
hoặc false
. Đối với chế độ thiết lập của tôi, kết quả trả về sẽ là true
.
window.screen.isExtended;
// Returns `true` or `false`.
Phương thức getScreenDetails()
Bây giờ, tôi đã biết rằng thiết lập hiện tại là nhiều màn hình, tôi có thể biết thêm thông tin về
màn hình thứ hai bằng Window.getScreenDetails()
. Khi gọi hàm này, lời nhắc cấp quyền sẽ hiển thị
hỏi tôi liệu trang web có thể mở và đặt các 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 (promise)
phân giải bằng đối tượng ScreenDetailed
. Trên MacBook Pro 13 có iPad được kết nối,
bao gồm một 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
. Lưu ý giá trị của
left
dành cho iPad có giá từ 1680
, chính xác là width
của màn hình tích hợp. Chiến dịch 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, trên đầu
với nhau, v.v.). Giờ đây, mỗi màn hình cũng đã có dữ liệu để cho biết đó có phải là màn hình isInternal
hay không
và liệu đó có phải là isPrimary
hay không. Lưu ý rằng màn hình tích hợp
không nhất thiết 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 theo các vị trí 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
Điều duy nhất còn thiếu bây giờ là cách phát hiện khi nào 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 điều đó: nó sẽ kích hoạt bất cứ khi nào chòm sao trên màn hình được sửa đổi. (Thông báo
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ột màn hình mới hoặc một
màn hình hiện tại đang được cắm điện hoặc rút phích cắm (thực tế hoặc ảo trong trường hợp là của Sidecar).
Lưu ý rằng bạn cần tra cứu thông tin chi tiết của màn hình mới một cách không đồng bộ, sự kiện screenschange
không cung cấp dữ liệu này. Để tra cứu thông tin chi tiết trên màn hình, hãy sử dụng đối tượng trực tiếp từ một bộ nhớ đệm
Giao diện Screens
.
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 tôi 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ể lắng nghe
Sự kiện change
.
const firstScreen = (await window.getScreenDetails())[0];
firstScreen.addEventListener('change', async (event) => {
console.log('The first screen has changed.', event, firstScreen);
});
Tuỳ chọn toàn màn hình mới
Cho đến nay, bạn có thể yêu cầu hiển thị các phần tử ở chế độ toàn màn hình thông qua
requestFullScreen()
. Phương thức này sẽ lấy tham số options
mà bạn có thể truyền
FullscreenOptions
. Cho đến nay,
tài sản duy nhất 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 nào để bắt đầu chế độ xem toàn màn hình. Ví dụ: nếu bạn muốn đặt làm màn hình chính
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);
}
Ống polyfill
Không thể polyfill API Quản lý cửa sổ, nhưng bạn có thể chèn hình dạng của nó để bạn có thể lập trình độc quyền dựa trên 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, đó là các sự kiện thay đổi màn hình khác nhau và thuộc tính screen
của
FullscreenOptions
, sẽ không bao giờ kích hoạt hoặc tự động bị bỏ qua tương ứng bằng
các trình duyệt không hỗ trợ.
Bản minh hoạ
Nếu bạn là bất kỳ ai như tôi, bạn hãy theo dõi chặt chẽ sự phát triển của tiền mã hoá. (Thực ra thì không phải vì tôi yêu hành tinh này, nhưng cho mục đích của bài viết này, giả sử tôi did.) Để theo dõi các loại tiền mã hoá mà tôi sở hữu, tôi đã phát triển một ứng dụng web cho phép tôi quan sát thị trường trong mọi tình huống trong cuộc sống, chẳng hạn như khi tôi nằm trên giường, nơi tôi có thiết lập màn hình đơn.
Vấn đề tiền mã hóa đang diễn ra và thị trường có thể trở nên sôi động bất cứ lúc nào. Nếu điều này xảy ra, tôi có thể nhanh chóng hãy di chuyển đến bàn làm việc của tôi tại nơi tôi đã thiết lập nhiều màn hình. Tôi có thể nhấp vào cửa sổ của bất kỳ đơn vị tiền tệ nào và xem nhanh toàn bộ 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 gần đây của tôi đã chụp trong lần tắm máu YCY vừa qua. Nó bắt gặp tôi hoàn toàn mất cảnh giác và để tôi đ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ạ có sự cố.
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 phiên bản cốt lõi nguyên tắc xác định trong Kiểm soát quyền truy cập vào các tính năng nền tảng web mạnh mẽ, bao gồm cả quyền kiểm soát của người dùng, tính minh bạch và công thái học. Window Management API hiển thị thông tin mới về các màn hình kết nối với một thiết bị, tăng bề mặt tạo vân tay số của người dùng, đặc biệt là những người có nhiều màn hình được kết nối liên tục với thiết bị của họ. Như một giảm thiểu mối lo ngại về quyền riêng tư này, nên các thuộc tính màn hình bị lộ sẽ đượ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ần có sự cho phép của người dùng để các trang web sử dụng được chế độ nhiều màn hình thông tin và đặt cửa sổ lên màn hình khác. Mặc dù Chromium trả về nhãn màn hình chi tiết, trình duyệt có thể trả về các nhãn ít mang tính mô tả hơn (hoặc thậm chí là 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 này. Họ có thể chấp nhận hoặc từ chối 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 có liên quan của Các nhóm chính sách nguyên tử phần cài đặt.
Sự minh bạch
Thực tế cho thấy quyền sử dụng API Quản lý cửa sổ đã được cấp hay chưa hiển thị trong thông tin trang web của trình duyệt và cũng có thể truy vấn được qua API Quyền.
Khả năng lưu trữ cố định quyền
Trình duyệt vẫn duy trì các quyền được cấp. Quyền này có thể bị thu hồi qua trang web của trình duyệt của bạn.
Phản hồi
Nhóm Chrome muốn biết ý kiến của bạn về trải nghiệm của bạn với API Quản lý cửa sổ.
Cho chúng tôi biết về thiết kế API
Có điều gì về API không hoạt động như bạn mong đợi không? Hoặc có phương thức nào bị thiếu hoặc thuộc tính nào bạn cần để triển khai ý tưởng của mình? Có câu hỏi hoặc nhận xét về bảo mật mẫu?
- 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 kho lưu trữ hiện có vấn đề.
Báo cáo sự cố về triển khai
Bạn có phát hiện lỗi trong quá trình 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?
- Báo cáo lỗi tại new.crbug.com. Hãy nhớ cung cấp càng nhiều thông tin chi tiết càng tốt
có thể, 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.
Hiện thông tin hỗ trợ về API này
Bạn có dự định sử dụng API Quản lý cửa sổ không? Sự hỗ trợ công khai của bạn sẽ giúp Chrome ưu tiên các tính năng và cho các nhà cung cấp trình duyệt khác biết tầm quan trọng của việc hỗ trợ họ.
- Chia sẻ cách bạn dự định sử dụng tài khoản này trên chuỗi bài thuyết trình về WICG.
- Gửi một bài đăng đến @ChromiumDev kèm theo hashtag
#WindowManagement
và cho chúng tôi biết bạn đang sử dụng ở đâu và như thế nào. - Hãy yêu cầu các nhà cung cấp trình duyệt khác triển khai API này.
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ạ API Quản lý cửa sổ | Bản minh hoạ API Quản lý cửa sổ nguồn
- Lỗi theo dõi Chromium
- Mục ChromeStatus.com
- Thành phần nháy:
Blink>Screen>MultiScreen
- Xem xét thẻ
- Ý định thử nghiệm
Xác nhận
Chỉnh sửa thông số API Quản lý cửa sổ Victor Costan, Joshua Bell và Mike Wasserman. API này được triển khai bởi Mike Wasserman và Adrienne Walker. Bài viết này được đánh giá bởi Joe Medley, François Beaufort, và Kayce Basques. Cảm ơn Laura Torrent Puig đã chụp ảnh.