تتيح واجهة برمجة التطبيقات Document Picture-in-Picture API فتح نافذة دائمًا في المقدّمة يمكن ملؤها بمحتوى HTML عشوائي. وتوفّر هذه الواجهة ميزات إضافية مقارنةً بواجهة برمجة التطبيقات الحالية لميزة "نافذة ضمن النافذة" في <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>
محدودة من حيث الأسلوب والمدخلات. من خلال ميزة "عرض مستند كامل في نافذة ضمن النافذة"، يمكن للموقع الإلكتروني دمج أحداث بث فيديو متعددة بسهولة في نافذة "نافذة ضمن النافذة" واحدة بدون الحاجة إلى الاعتماد على حيل اللوحة وتوفير عناصر تحكّم مخصّصة، مثل إرسال رسالة أو كتم صوت مستخدم آخر أو رفع اليد.
الإنتاجية
أظهرت الأبحاث أنّ المستخدمين بحاجة إلى مزيد من الطرق لزيادة إنتاجيتهم على الويب. تمنح ميزة "المستند في وضع نافذة ضمن النافذة" تطبيقات الويب المرونة اللازمة لإنجاز المزيد. سواء كان ذلك من خلال تعديل النصوص أو تدوين الملاحظات أو قوائم المهام أو المراسلة والمحادثة أو أدوات التصميم والتطوير، يمكن الآن لتطبيقات الويب إبقاء المحتوى متاحًا في أي وقت.
الواجهة
أماكن إقامة
documentPictureInPicture.window
- تعرض النافذة الحالية المفتوحة بميزة "نافذة ضمن النافذة"، إن توفّرت. بخلاف ذلك، يتم عرض
null
.
الطُرق
documentPictureInPicture.requestWindow(options)
تعرِض وعدًا يتم حلّه عند فتح نافذة "نافذة ضمن النافذة". يتم رفض الوعد في حال استدعائه بدون إيماءة من المستخدم. يحتوي قاموس
options
على العناصر التالية الاختيارية:width
- ضبط العرض الأولي لـ "نافذة ضمن النافذة"
height
- ضبط الارتفاع الأولي لـ "نافذة ضمن النافذة"
disallowReturnToOpener
- يخفي الزر "الرجوع إلى علامة التبويب" في نافذة "النافذة ضمن النافذة" إذا كان القيمة true. تكون القيمة التلقائية هي خطأ.
preferInitialWindowPlacement
- فتح نافذة "الصورة في الصورة" في موضعها وحجمها التلقائيَين إذا كان صحيحًا تكون القيمة التلقائية هي خطأ.
الفعاليات
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()
للتركيز على نافذة المشغّل من نافذة "نافذة ضمن النافذة". تتطلّب هذه الطريقة إيماءة من المستخدِم.
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 في واجهة برمجة التطبيقات "صورة في صورة" للمستندات. احرص على الاطّلاع على رمز المصدر.
Pomodoro
يستفيد تطبيق الويب Tomodoro أيضًا من واجهة برمجة التطبيقات Document Picture-in-Picture API عند توفّرها. اطّلِع على طلب سحب GitHub.
مشاركة ملاحظاتك
يمكنك الإبلاغ عن المشاكل على GitHub مع تقديم اقتراحات والأسئلة.