동영상 컨트롤에 PIP 모드를 추가하는 방법

François Beaufort
François Beaufort

현대적인 방식

PIP 모드 웹 API를 사용하면 웹사이트에서는 항상 다른 창 위에 플로팅 동영상 창을 만들어 사용자가 기기의 다른 콘텐츠 사이트 또는 애플리케이션과 상호작용하는 동안 미디어를 계속 사용할 수 있습니다.

아래 예는 사용자가 동영상에서 PIP 모드를 전환하는 데 사용할 수 있는 버튼을 만드는 방법을 보여줍니다.

togglePipButton.addEventListener("click", async (event) => {
  togglePipButton
.disabled = true;
 
try {
   
if (video !== document.pictureInPictureElement) {
      await video
.requestPictureInPicture();
   
} else {
      await document
.exitPictureInPicture();
   
}
 
} finally {
    togglePipButton
.disabled = false;
 
}
});

video
.addEventListener("enterpictureinpicture", (event) => {
  togglePipButton
.classList.add("on");
});

video
.addEventListener("leavepictureinpicture", (event) => {
  togglePipButton
.classList.remove("on");
});

/* Feature detection */
if ("pictureInPictureEnabled" in document) {
 
// Set button ability depending on whether Picture-in-Picture can be used.
  setPipButton
();
  video
.addEventListener("loadedmetadata", setPipButton);
  video
.addEventListener("emptied", setPipButton);
} else {
 
// Hide button if Picture-in-Picture is not supported.
  togglePipButton
.hidden = true;
}

function setPipButton() {
  togglePipButton
.disabled =
    video
.readyState === 0 ||
   
!document.pictureInPictureEnabled ||
    video
.disablePictureInPicture;
}

기존의 방식

PIP 모드 Web API를 사용할 수 있게 되기 전에는 다른 창 위에 항상 플로팅 동영상 창을 만들 수 있는 방법이 없었습니다. 하지만 CSS를 사용하면 웹페이지의 다른 요소 위에서 동영상을 재생할 수 있습니다.

아래 예는 사용자가 버튼을 클릭할 때 웹페이지의 오른쪽 하단에 있는 다른 요소 위에 동영상을 표시하는 방법을 보여줍니다.

toggleFakePipButton.addEventListener("click", (event) => {
  video
.classList.toggle("fake-pip");
});
/* Place the video in the bottom right corner on top of everything else via CSS. */
video
.fake-pip {
 
position: fixed;
 
z-index: 1000;
 
bottom: 10px;
 
right: 10px;
}

추가 자료

HTMLCSSJS
<!DOCTYPE html>
<html lang="en">
 
<head>
   
<meta charset="utf-8" />
   
<meta name="viewport" content="width=device-width, initial-scale=1" />
    <link
      rel="icon"
      href="data:image/svg+xml,
<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>📺</text></svg>"
    />
   
<title>How to add Picture-in-Picture to video controls</title>
 
</head>
 
<body>
   
<h1>How to add Picture-in-Picture to video controls</h1>
   
<button id="togglePipButton">Picture-in-Picture</button>
   
<button id="toggleFakePipButton">Fake Picture-in-Picture</button>
   
<video autoplay muted playsinline loop src="https://storage.googleapis.com/media-session/caminandes/short.mp4"></video>
 
</body>
</html>

       
:root {
 
color-scheme: dark light;
}
html
{
 
box-sizing: border-box;
}
*,
*:before,
*:after {
 
box-sizing: inherit;
}
body
{
 
margin: 1rem;
 
font-family: system-ui, sans-serif;
}
button:before {
 
content: "Enter ";
}
button
.on:before {
 
content: "Leave ";
}
video
{
 
display: block;
 
margin-top: 10px;
 
max-width: 100%;
}
video
.fake-pip {
 
position: fixed;
 
z-index: 1000;
 
bottom: 10px;
 
right: 10px;
}
       

       
const video = document.querySelector('video');
const togglePipButton = document.querySelector('#togglePipButton');
const toggleFakePipButton = document.querySelector('#toggleFakePipButton');

togglePipButton
.addEventListener("click", async (event) => {
  togglePipButton
.disabled = true;
 
try {
   
if (video !== document.pictureInPictureElement) {
      await video
.requestPictureInPicture();
   
} else {
      await document
.exitPictureInPicture();
   
}
 
} finally {
    togglePipButton
.disabled = false;
 
}
});

video
.addEventListener("enterpictureinpicture", (event) => {
  togglePipButton
.classList.add("on");
});

video
.addEventListener("leavepictureinpicture", (event) => {
  togglePipButton
.classList.remove("on");
});

/* Feature detection */
if ("pictureInPictureEnabled" in document) {
 
// Hide fake PiP button if Picture-in-Picture is supported.
  toggleFakePipButton
.hidden = true;
 
// Set button ability depending on whether Picture-in-Picture can be used.
  setPipButton
();
  video
.addEventListener("loadedmetadata", setPipButton);
  video
.addEventListener("emptied", setPipButton);
} else {
 
// Hide button if Picture-in-Picture is not supported.
  togglePipButton
.hidden = true;
}

function setPipButton() {
  togglePipButton
.disabled =
    video
.readyState === 0 ||
   
!document.pictureInPictureEnabled ||
    video
.disablePictureInPicture;
}

/* Fake Picture-in-Picture */
toggleFakePipButton
.addEventListener("click", (event) => {
  toggleFakePipButton
.classList.toggle("on");
  video
.classList.toggle("fake-pip");
});