3️⃣

JavaScript 20 Projects - 3 Picture In Picture

2023/08/17に公開

前言

這系列是課程 JavaScript Web Projects: 20 Projects to Build Your Portfolio 的筆記,學習利用 Javascript 做出各種互動網站。

以下是這系列的文章:

Project 1 Quote Generator
Project 2 Infinity Scroll
Project 3 Picture In Picture

目標

要實作出子母畫面的功能。

下面是這次要實作的畫面。範例的連結

Picture-In-Picture.png

建立 HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Picture in Picture</title>
    <link rel="icon" type="image/png" href="favicon.png">
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <!-- Video -->
    <video id="video" controls height="360" width="640" hidden></video>
    <!-- Button -->
    <div class="button-container">
        <button id="button">START</button>
    </div>
    <!-- Script -->
    <script src="script.js"></script>
</body>
</html>

建立 CSS

因為只有按鈕,所以直接找現成的,這次是從這個連結找的。

思考 javascript 所需要的動作

  1. 如何取得視窗的畫面?
  2. 如何控制進入子母畫面的模式?

動作解讀

如何取得視窗的畫面?

  1. 先利用 DOM 來取得 video 元素。
  2. 建立 selectMediaStream() 來選擇畫面。
    1. 利用 navigator.mediaDevices.getDisplayMedia() 來取得媒體來源,並設定變數mediaStream。
      • 這邊 navigator 是用來取得使用者設備相關資料。
    2. 並把 mediaStream 設定給影片元素的 srcObject 屬性。
    3. 藉由 srcObject 屬性,在下一步設定當載入時 (onloadedmetadata) 就會播放。
const videoElement = document.getElementById("video");

// Prompt to select media stream, pass to video element, then play
async function selectMediaStream() {
  try {
    const mediaStream = await navigator.mediaDevices.getDisplayMedia();
    videoElement.srcObject = mediaStream;
    videoElement.onloadedmetadata = () => {
      videoElement.play();
    };
  } catch (error) {
    // Catch Error Here
  }
}

selectMediaStream()

如何控制進入子母畫面的模式?

  1. 先利用 DOM 來取得 button 元素。
  2. 設定當點擊按鈕時會觸發的動作。
  3. 利用 await videoElement.requestPictureInPicture(); 來進入子母畫面模式。
  4. 在開始子母畫面動作的前後設定按鈕的功能,讓他在子母畫面完成前按壓不會有多的動作。
const button = document.getElementById("button");

button.addEventListener("click", async () => {
  // Disable Button
  button.disabled = true;
  // Start Picture in Picture
  await videoElement.requestPictureInPicture();
  // Reset Button
  button.disabled = false;
});

完整的Javascript程式碼

const videoElement = document.getElementById("video");
const button = document.getElementById("button");

// Prompt to select media stream, pass to video element, then play
async function selectMediaStream() {
  try {
    const mediaStream = await navigator.mediaDevices.getDisplayMedia();
    videoElement.srcObject = mediaStream;
    videoElement.onloadedmetadata = () => {
      videoElement.play();
    };
  } catch (error) {
    // Catch Error Here
  }
}

button.addEventListener("click", async () => {
  // Disable Button
  button.disabled = true;
  // Start Picture in Picture
  await videoElement.requestPictureInPicture();
  // Reset Button
  button.disabled = false;
});

// On Load
selectMediaStream();

文章參考

An Introduction to the Picture-in-Picture Web API

Using the Screen Capture API

Watch video using Picture-in-Picture

Discussion