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

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

Browser Support

  • Хром: 116.
  • Край: 116.
  • Firefox: не поддерживается.
  • Safari: не поддерживается.

Source

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

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

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

Текущий статус

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

Варианты использования

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

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

Видеоконференцсвязь

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

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

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

Интерфейс

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

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

Методы

documentPictureInPicture.requestWindow(options)

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

width
Задает начальную ширину окна «Картинка в картинке».
height
Задает начальную высоту окна «Картинка в картинке».
disallowReturnToOpener
Скрывает кнопку «Вернуться к вкладке» в окне «Картинка в картинке», если установлено значение true. По умолчанию установлено значение false.
preferInitialWindowPlacement
Открывать окно «Картинка в картинке» в положении и размере по умолчанию, если установлено значение true. По умолчанию установлено значение false.

События

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,
  });
});

Откройте окно «Картинка в картинке» в его положении и размере по умолчанию.

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

pipButton.addEventListener("click", async () => {
  // Open a Picture-in-Picture window in its default position / size.
  const pipWindow = await documentPictureInPicture.requestWindow({
    preferInitialWindowPlacement: 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 — веб-приложение «Помодоро».
Окно «картинка в картинке» в Томодоро.

Поделитесь своим мнением

Отправляйте сообщения об ошибках на GitHub с предложениями и вопросами.