Картинка в картинке для любого элемента, а не только для <video>

Франсуа Бофор
François Beaufort

Поддержка браузера

  • 116
  • 116
  • Икс
  • Икс

Источник

API Document Picture-in-Picture позволяет открывать постоянное окно, которое можно заполнить произвольным HTML-содержимым. Он расширяет существующий API «Картинка в картинке» для <video> , который позволяет помещать в окно «Картинка в картинке» только элемент HTML <video> .

Окно «Картинка в картинке» в API «Картинка в картинке документа» похоже на пустое окно того же происхождения, открытое с помощью window.open() , с некоторыми отличиями:

  • Окно «Картинка в картинке» располагается поверх других окон.
  • Окно «Картинка в картинке» никогда не переживет открывающееся окно.
  • В окне «Картинка в картинке» невозможно перемещаться.
  • Положение окна «Картинка в картинке» не может быть установлено на веб-сайте.
Окно «картинка в картинке», воспроизводящее трейлер Sintel.
Окно «Картинка в картинке», созданное с помощью API «Картинка в картинке» документа ( демо ).

Текущее состояние

Шаг Положение дел
1. Создайте объяснитель Полный
2. Создайте первоначальный проект спецификации. В ходе выполнения
3. Соберите отзывы и доработайте дизайн В ходе выполнения
4. Пробная версия происхождения Полный
5. Запуск Полный (Десктоп)

Случаи использования

Пользовательский видеоплеер

Веб-сайт может обеспечить просмотр видео «картинка в картинке» с помощью существующего API «картинка в картинке» для <video> , однако его возможности очень ограничены. Существующее окно «Картинка в картинке» принимает мало входных данных и имеет ограниченные возможности для их стилизации. Благодаря полному документу в формате «картинка в картинке» веб-сайт может предоставлять настраиваемые элементы управления и входные данные (например, субтитры , списки воспроизведения, скруббер времени, лайки и антипатии видео), чтобы улучшить работу пользователя с видео «картинка в картинке».

Видео-конференция

Пользователи часто покидают вкладку браузера во время сеанса видеоконференции по разным причинам (например, показ другой вкладки во время вызова или многозадачность), но при этом желают видеть вызов, поэтому это основной вариант использования функции «Картинка в Картина. Опять же, текущий опыт, который веб-сайт видеоконференций может предоставить через API «картинка в картинке» для <video> , ограничен по стилю и вводу. Благодаря полному документу в режиме «Картинка в картинке» веб-сайт может легко объединить несколько видеопотоков в одно окно PiP, не прибегая к хакам холста и предоставляя настраиваемые элементы управления, такие как отправка сообщения, отключение звука другого пользователя или поднятие руки.

Производительность

Исследования показали, что пользователям нужно больше способов продуктивно работать в Интернете. Документ в режиме «Картинка в картинке» дает веб-приложениям гибкость, позволяющую достигать большего. Будь то редактирование текста, создание заметок, списки задач, обмен сообщениями и чат или инструменты дизайна и разработки, веб-приложения теперь могут всегда обеспечивать доступность своего контента.

Интерфейс

Характеристики

documentPictureInPicture.window
Возвращает текущее окно «Картинка в картинке», если оно есть. В противном случае возвращает null .

Методы

documentPictureInPicture.requestWindow(options)

Возвращает обещание, которое выполняется при открытии окна «Картинка в картинке». Промис отклоняется, если он вызывается без жестов пользователя. Словарь options содержит следующие необязательные элементы:

width
Устанавливает начальную ширину окна «Картинка в картинке».
height
Устанавливает начальную высоту окна «Картинка в картинке».
disallowReturnToOpener
Скрывает кнопку «Назад на вкладку» в окне «Картинка в картинке», если установлено значение true. По умолчанию это ложь.

События

documentPictureInPicture.onenter
Вызывается в documentPictureInPicture при открытии окна «Картинка в картинке».

Примеры

Следующий HTML-код устанавливает пользовательский видеопроигрыватель и элемент кнопки для открытия видеопроигрывателя в окне «картинка в картинке».

<div id="playerContainer">
  <div id="player">
    <video id="video"></video>
  </div>
</div>
<button id="pipButton">Open Picture-in-Picture window</button>

Откройте окно «Картинка в картинке»

Следующий код JavaScript вызывает documentPictureInPicture.requestWindow() , когда пользователь нажимает кнопку, чтобы открыть пустое окно «Картинка в картинке». Возвращенное обещание разрешается с помощью объекта JavaScript окна «Картинка в картинке». Видеоплеер перемещается в это окно с помощью append() .

pipButton.addEventListener('click', async () => {
  const player = document.querySelector("#player");

  // Open a Picture-in-Picture window.
  const pipWindow = await documentPictureInPicture.requestWindow();

  // Move the player to the Picture-in-Picture window.
  pipWindow.document.body.append(player);
});

Установите размер окна «Картинка в картинке»

Чтобы установить размер окна «Картинка в картинке», установите параметры width и height documentPictureInPicture.requestWindow() на желаемый размер окна «Картинка в картинке». Chrome может ограничить значения параметров, если они слишком велики или слишком малы для удобного размера окна.

pipButton.addEventListener("click", async () => {
  const player = document.querySelector("#player");

  // Open a Picture-in-Picture window whose size is
  // the same as the player's.
  const pipWindow = await documentPictureInPicture.requestWindow({
    width: player.clientWidth,
    height: player.clientHeight,
  });

  // Move the player to the Picture-in-Picture window.
  pipWindow.document.body.append(player);
});

Скрыть кнопку «Назад на вкладку» в окне «Картинка в картинке».

Чтобы скрыть кнопку в окне «Картинка в картинке», которая позволяет пользователю вернуться на вкладку открытия, установите для параметра disallowReturnToOpener в documentPictureInPicture.requestWindow() значение true .

pipButton.addEventListener("click", async () => {
  // Open a Picture-in-Picture window which hides the "back to tab" button.
  const pipWindow = await documentPictureInPicture.requestWindow({
    disallowReturnToOpener: true,
  });
});

Копирование таблиц стилей в окно «Картинка в картинке»

Чтобы скопировать все таблицы стилей CSS из исходного окна, просмотрите styleSheets явно связанные с документом или встроенные в него, и добавьте их в окно «Картинка в картинке». Обратите внимание, что это одноразовая копия.

pipButton.addEventListener("click", async () => {
  const player = document.querySelector("#player");

  // Open a Picture-in-Picture window.
  const pipWindow = await documentPictureInPicture.requestWindow();

  // Copy style sheets over from the initial document
  // so that the player looks the same.
  [...document.styleSheets].forEach((styleSheet) => {
    try {
      const cssRules = [...styleSheet.cssRules].map((rule) => rule.cssText).join('');
      const style = document.createElement('style');

      style.textContent = cssRules;
      pipWindow.document.head.appendChild(style);
    } catch (e) {
      const link = document.createElement('link');

      link.rel = 'stylesheet';
      link.type = styleSheet.type;
      link.media = styleSheet.media;
      link.href = styleSheet.href;
      pipWindow.document.head.appendChild(link);
    }
  });

  // Move the player to the Picture-in-Picture window.
  pipWindow.document.body.append(player);
});

Обработка закрытия окна «Картинка в картинке»

Прослушайте событие "pagehide" окна, чтобы узнать, когда окно «Картинка в картинке» закрывается (либо потому, что оно было инициировано веб-сайтом, либо потому, что пользователь закрыл его вручную). Обработчик событий — хорошее место для возврата элементов из окна «Картинка в картинке», как показано ниже.

pipButton.addEventListener("click", async () => {
  const player = document.querySelector("#player");

  // Open a Picture-in-Picture window.
  const pipWindow = await documentPictureInPicture.requestWindow();

  // Move the player to the Picture-in-Picture window.
  pipWindow.document.body.append(player);

  // Move the player back when the Picture-in-Picture window closes.
  pipWindow.addEventListener("pagehide", (event) => {
    const playerContainer = document.querySelector("#playerContainer");
    const pipPlayer = event.target.querySelector("#player");
    playerContainer.append(pipPlayer);
  });
});

Закройте окно «Картинка в картинке» программно, используя метод close() .

// Close the Picture-in-Picture window programmatically. 
// The "pagehide" event will fire normally.
pipWindow.close();

Слушайте, когда веб-сайт переходит в режим «картинка в картинке»

Прослушайте событие "enter" в documentPictureInPicture , чтобы узнать, когда открывается окно «Картинка в картинке». Событие содержит объект window для доступа к окну «картинка в картинке».

documentPictureInPicture.addEventListener("enter", (event) => {
  const pipWindow = event.window;
});

Доступ к элементам в окне «Картинка в картинке»

Доступ к элементам в окне «Картинка в картинке» осуществляется либо из объекта, возвращаемого documentPictureInPicture.requestWindow() , либо с помощью documentPictureInPicture.window , как показано ниже.

const pipWindow = documentPictureInPicture.window;
if (pipWindow) {
  // Mute video playing in the Picture-in-Picture window.
  const pipVideo = pipWindow.document.querySelector("#video");
  pipVideo.muted = true;
}

Обработка событий из окна «Картинка в картинке»

Создавайте кнопки и элементы управления и реагируйте на события ввода пользователя, такие как "click" , как обычно в JavaScript.

// Add a "mute" button to the Picture-in-Picture window.
const pipMuteButton = pipWindow.document.createElement("button");
pipMuteButton.textContent = "Mute";
pipMuteButton.addEventListener("click", () => { 
  const pipVideo = pipWindow.document.querySelector("#video");
  pipVideo.muted = true;
});
pipWindow.document.body.append(pipMuteButton);

Изменение размера окна «Картинка в картинке»

Используйте методы окна resizeBy() и resizeTo() , чтобы изменить размер окна «картинка в картинке». Оба метода требуют жеста пользователя.

const resizeButton = pipWindow.document.createElement('button');
resizeButton.textContent = 'Resize';
resizeButton.addEventListener('click', () => {
  // Expand the Picture-in-Picture window's width by 20px and height by 30px.
  pipWindow.resizeBy(20, 30);
});
pipWindow.document.body.append(resizeButton);

Фокус открывающегося окна

Используйте метод focus() Window, чтобы сфокусировать окно открытия из окна «Картинка в картинке». Этот метод требует жеста пользователя.

const returnToTabButton = pipWindow.document.createElement("button");
returnToTabButton.textContent = "Return to opener tab";
returnToTabButton.addEventListener("click", () => {
  window.focus();
});
pipWindow.document.body.append(returnToTabButton);

Режим отображения CSS «картинка в картинке»

Используйте режим отображения CSS picture-in-picture для написания определенных правил CSS, которые применяются только тогда, когда веб-приложение (часть) отображается в режиме «картинка в картинке».

@media all and (display-mode: picture-in-picture) {
  body {
    margin: 0;
  }
  h1 {
    font-size: 0.8em;
  }
}

Обнаружение функций

Чтобы проверить, поддерживается ли API «Картинка в картинке» документа, используйте:

if ('documentPictureInPicture' in window) {
  // The Document Picture-in-Picture API is supported.
}

Демо

ВидеоJS-плеер

Вы можете поиграть с демо-плеером VideoJS Document Picture-in-Picture API. Обязательно ознакомьтесь с исходным кодом .

Помидоро

Tomodoro , веб-приложение pomodoro, также использует API Document Picture-in-Picture, когда он доступен (см. запрос на извлечение GitHub ).

Снимок экрана Tomodoro, веб-приложения Pomodoro.
Окно «картинка в картинке» в Tomodoro.

Обратная связь

Пожалуйста, сообщайте о проблемах на GitHub с предложениями и вопросами.

Благодарности

Изображение героя Джейкоба Оуэнса .