Chrome 66 позволяет веб-страницам использовать дополнительный подключенный дисплей через API-интерфейс Presentation и управлять его содержимым через API-интерфейс Presentation Receiver .
Фон
До сих пор веб-разработчики могли создавать возможности, в которых пользователь мог бы видеть локальный контент в Chrome, который отличается от контента, который он видел бы на удаленном дисплее, но при этом имел возможность контролировать этот опыт локально. Примеры включают управление очередью воспроизведения на youtube.com во время воспроизведения видео на телевизоре или просмотр слайдов с заметками докладчика на ноутбуке во время полноэкранной презентации в сеансе Hangouts.
Однако существуют сценарии, когда пользователи могут просто захотеть представить контент на втором подключенном дисплее. Например, представьте себе пользователя в конференц-зале, оснащенного проектором, к которому он подключен через кабель HDMI. Вместо зеркального отображения презентации на удаленном конечном устройстве пользователь действительно хочет представить слайды на проекторе в полноэкранном режиме , оставив экран ноутбука доступным для заметок докладчика и управления слайдами. Хотя автор сайта мог бы поддержать это очень элементарным способом (например, появлением нового окна, которое пользователь затем должен вручную перетащить на дополнительный дисплей и развернуть в полноэкранный режим), это громоздко и обеспечивает несогласованное взаимодействие между локальным и удаленным доступом. презентация.
Представить страницу
Позвольте мне рассказать вам, как использовать Presentation API для представления веб-страницы на дополнительном подключенном дисплее. Конечный результат доступен по адресу https://googlechrome.github.io/samples/presentation-api/ .
Сначала мы создадим новый объект PresentationRequest
, который будет содержать URL-адрес, который мы хотим представить на дополнительном подключенном дисплее.
const presentationRequest = new PresentationRequest('receiver.html');
In this article, I won’t cover use cases where the parameter passed to
`PresentationRequest` can be an array like `['cast://foo’, 'apple://foo',
'https://example.com']` as this is not relevant there.
We can now monitor presentation display availability and toggle a "Present"
button visibility based on presentation displays availability. Note that we can
also decide to always show this button.
<aside class="caution"><b>Caution:</b> The browser may use more energy while the <code>availability</code> object is alive
and actively listening for presentation display availability changes. Please
use it with caution in order to save energy on mobile.</aside>
```js
presentationRequest.getAvailability()
.then(availability => {
console.log('Available presentation displays: ' + availability.value);
availability.addEventListener('change', function() {
console.log('> Available presentation displays: ' + availability.value);
});
})
.catch(error => {
console.log('Presentation availability not supported, ' + error.name + ': ' +
error.message);
});
Для отображения приглашения к отображению презентации требуется жест пользователя, например нажатие кнопки. Итак, давайте вызовем presentationRequest.start()
при нажатии кнопки и подождем, пока обещание разрешится, как только пользователь выберет отображение презентации (например, дополнительный подключенный дисплей в нашем случае).
function onPresentButtonClick() {
presentationRequest.start()
.then(connection => {
console.log('Connected to ' + connection.url + ', id: ' + connection.id);
})
.catch(error => {
console.log(error);
});
}
Список, представленный пользователю, также может включать удаленные конечные точки, такие как устройства Chromecast, если вы подключены к сети, рекламирующей их. Обратите внимание, что зеркальных дисплеев нет в списке. См. http://crbug.com/840466 .
Когда обещание разрешается, веб-страница по URL-адресу объекта PresentationRequest
отображается на выбранном дисплее. И вуаля!
Теперь мы можем пойти дальше и отслеживать события «закрытия» и «завершения», как показано ниже. Обратите внимание, что можно повторно подключиться к «закрытому» presentationConnection
с помощью presentationRequest.reconnect(presentationId)
, где presentationId
— это идентификатор предыдущего объекта presentationRequest
.
function onCloseButtonClick() {
// Disconnect presentation connection but will allow reconnection.
presentationConnection.close();
}
presentationConnection.addEventListener('close', function() {
console.log('Connection closed.');
});
function onTerminateButtonClick() {
// Stop presentation connection for good.
presentationConnection.terminate();
}
presentationConnection.addEventListener('terminate', function() {
console.log('Connection terminated.');
});
Общайтесь со страницей
Теперь вы думаете: это хорошо, но как мне передавать сообщения между моей страницей контроллера (той, которую мы только что создали) и страницей-получателем (той, которую мы передали объекту PresentationRequest
)?
Сначала давайте получим существующие соединения на странице получателя с помощью navigator.presentation.receiver.connectionList
и прослушаем входящие соединения, как показано ниже.
// Receiver page
navigator.presentation.receiver.connectionList
.then(list => {
list.connections.map(connection => addConnection(connection));
list.addEventListener('connectionavailable', function(event) {
addConnection(event.connection);
});
});
function addConnection(connection) {
connection.addEventListener('message', function(event) {
console.log('Message: ' + event.data);
connection.send('Hey controller! I just received a message.');
});
connection.addEventListener('close', function(event) {
console.log('Connection closed!', event.reason);
});
}
Соединение, получающее сообщение, запускает событие «сообщение», которое вы можете прослушать. Сообщение может быть строкой, большим двоичным объектом, ArrayBuffer или ArrayBufferView. Отправить его так же просто, как вызвать connection.send(message)
со страницы контроллера или страницы получателя.
// Controller page
function onSendMessageButtonClick() {
presentationConnection.send('Hello!');
}
presentationConnection.addEventListener('message', function(event) {
console.log('I just received ' + event.data + ' from the receiver.');
});
Поиграйте с примером на https://googlechrome.github.io/samples/presentation-api/, чтобы понять, как он работает. Я уверен, что вам это понравится так же, как и мне.
Образцы и демо
Ознакомьтесь с официальным образцом Chrome, который мы использовали для этой статьи.
Я также рекомендую интерактивную демонстрацию Photowall . Это веб-приложение позволяет нескольким контроллерам совместно представлять слайд-шоу из фотографий на презентационном дисплее. Код доступен по адресу https://github.com/GoogleChromeLabs/presentation-api-samples .
Еще одна вещь
В Chrome есть меню браузера «Cast», которое пользователи могут вызвать в любой момент при посещении веб-сайта. Если вы хотите управлять представлением по умолчанию для этого меню, назначьте navigator.presentation.defaultRequest
пользовательскому presentationRequest
, созданному ранее.
// Make this presentation the default one when using the "Cast" browser menu.
navigator.presentation.defaultRequest = presentationRequest;
Советы разработчикам
Чтобы проверить страницу-получатель и отладить ее, перейдите на внутреннюю страницу chrome://inspect
, выберите «Другое» и нажмите ссылку «проверить» рядом с представленным в данный момент URL-адресом.
Вы также можете посетить внутреннюю страницу chrome://media-router-internals
чтобы узнать больше о внутренних процессах обнаружения/доступности.
Что дальше
Начиная с Chrome 66, поддерживаются платформы ChromeOS, Linux и Windows. Поддержка Mac появится позже .
Ресурсы
- Статус функции Chrome: https://www.chromestatus.com/features#presentation%20api.
- Ошибки реализации: https://crbug.com/?q=comComponent:Blink>PresentationAPI.
- Спецификация API презентации: https://w3c.github.io/presentation-api/
- Проблемы со спецификациями: https://github.com/w3c/presentation-api/issues.