Document Picture-in-Picture API מאפשר לפתוח חלון שמוצג תמיד מעל שאר החלונות, ואפשר לאכלס אותו בתוכן HTML שרירותי. הוא מרחיב את Picture-in-Picture API הקיים ל-<video>
, שמאפשר רק להוסיף רכיב HTML מסוג <video>
לחלון 'תמונה בתוך תמונה'.
החלון מסוג 'תמונה בתוך תמונה' ב-Document Picture-in-Picture API דומה לחלון ריק מאותו מקור שנפתח באמצעות window.open()
, עם כמה הבדלים:
- החלון 'תמונה בתוך תמונה' צף על מעל חלונות אחרים.
- החלון של 'תמונה בתוך תמונה' אף פעם לא יהיה גדול יותר מהחלון הפתוח.
- אי אפשר לנווט בחלון 'תמונה בתוך תמונה'.
- באתר אין אפשרות להגדיר את המיקום של חלון 'תמונה בתוך תמונה'.
הסטטוס הנוכחי
שלב | סטטוס |
---|---|
1. יצירת הסבר | הושלם |
2. יצירת טיוטה ראשונית של המפרט | בתהליך |
3. איסוף משוב וביצוע שינויים בעיצוב | בתהליך |
4. גרסת מקור לניסיון | הושלם |
5. השקה | הושלם (במחשב) |
תרחישים לדוגמה
נגן וידאו בהתאמה אישית
אתר יכול לספק חוויית צפייה בסרטון בחלון צף באמצעות Picture-in-Picture API הקיים ל-<video>
, אבל החוויה הזו מוגבלת מאוד. חלון 'תמונה בתוך תמונה' הקיים מקבל מעט קלט, ויש לו יכולת מוגבלת לעיצוב אותו. כשהמסמך מוצג במסך מפוצל, האתר יכול לספק פקדים וממשקי קלט בהתאמה אישית (לדוגמה, כתוביות, פלייליסטים, סרגל זמן, סימון סרטונים בלייק או דיסלייק) כדי לשפר את חוויית הצפייה של המשתמש בסרטון במסך מפוצל.
שיחת ועידה בווידאו
משתמשים נוטים לעזוב את הכרטיסייה בדפדפן במהלך שיחת ועידה בווידאו מסיבות שונות (למשל, כדי להציג כרטיסייה אחרת בשיחה או כדי לבצע משימות נוספות) ועדיין רוצים לראות את השיחה. לכן, זהו תרחיש לדוגמה שבו כדאי להשתמש בתכונה 'תמונה בתוך תמונה'. שוב, החוויה הנוכחית שאתר של כנס וידאו יכול לספק דרך Picture-in-Picture API ל-<video>
מוגבלת בסגנון ובקלט. כשמשתמשים במסמך מלא במצב 'תמונה בתוך תמונה', האתר יכול לשלב בקלות כמה שידורי וידאו בחלון PiP אחד בלי להסתמך על האקינג של קנבס, ולספק אמצעי בקרה מותאמים אישית כמו שליחת הודעה, השבתת הקול של משתמש אחר או הרמת יד.
פרודוקטיביות
מחקרים הראו שמשתמשים צריכים עוד דרכים להיות פרודוקטיביים באינטרנט. התכונה 'מסמך ב'תמונה בתוך תמונה' מעניקה לאפליקציות אינטרנט גמישות לביצוע משימות נוספות. עכשיו תוכלו להשתמש באפליקציות אינטרנט ללא חשש שהתוכן שלהן לא יהיה נגיש, בין אם מדובר בעריכת טקסט, בכתיבת הערות, ברשימות משימות, בהעברת הודעות ובצ'אט או בכלים לעיצוב ולפיתוח.
ממשק
מאפיינים
documentPictureInPicture.window
- מחזירה את חלון התמונה בתוך תמונה הנוכחי, אם יש כזה. אחרת, הפונקציה מחזירה את הערך
null
.
שיטות
documentPictureInPicture.requestWindow(options)
הפונקציה מחזירה הבטחה (promise) שמתמלאת כשחלון עם תמונה בתוך תמונה נפתח. אם קוראים להבטחה בלי תנועת משתמש, היא תידחה. המילון
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);
שינוי הגודל של חלון תמונה בתוך תמונה
משתמשים בשיטות Window 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()
כדי להתמקד בחלון הפתיחה מהחלון עם תמונה בתוך תמונה. ל-method הזה נדרשת תנועת משתמש.
const returnToTabButton = pipWindow.document.createElement("button");
returnToTabButton.textContent = "Return to opener tab";
returnToTabButton.addEventListener("click", () => {
window.focus();
});
pipWindow.document.body.append(returnToTabButton);
מצב תצוגה של תמונה בתוך תמונה ב-CSS
משתמשים במצב התצוגה picture-in-picture
של CSS כדי לכתוב כללי CSS ספציפיים שחלים רק כש (חלק מ)אפליקציית האינטרנט מוצגת במצב 'תמונה בתוך תמונה'.
@media all and (display-mode: picture-in-picture) {
body {
margin: 0;
}
h1 {
font-size: 0.8em;
}
}
זיהוי תכונות
כדי לבדוק אם יש תמיכה ב-Document Picture-in-Picture API, משתמשים ב-:
if ('documentPictureInPicture' in window) {
// The Document Picture-in-Picture API is supported.
}
הדגמות
נגן VideoJS
אתם יכולים לנסות את הדגמה של נגן VideoJS עם Document Picture-in-Picture API. מומלץ לעיין בקוד המקור.
פומודורו
גם Tomodoro, אפליקציית אינטרנט ל-Pomodoro, משתמשת ב-Document Picture-in-Picture API כשהיא זמינה. בקשת ה-pull שלהם ב-GitHub.
שיתוף משוב
דיווח על בעיות ב-GitHub עם הצעות ושאלות.