عرض صفحات الويب على شاشات إضافية متصلة

فرانسوا بوفورت
فرانسوا بوفورت

يسمح Chrome 66 لصفحات الويب باستخدام عرض ثانوي مرفق من خلال Presentation API والتحكّم في محتواها من خلال واجهة برمجة تطبيقات استقبال العروض التقديمية.

1/2. يختار المستخدم شاشة ملحقة ثانوية
1/2- يختار المستخدم شاشة ملحقة ثانوية
2/2. يتم عرض صفحة الويب تلقائيًا على الشاشة التي تم اختيارها سابقًا.
2/2. يتم عرض صفحة ويب تلقائيًا على الشاشة التي تم اختيارها سابقًا.

الخلفية

حتى الآن، يمكن لمطوّري برامج الويب إنشاء تجارب تتيح للمستخدم رؤية محتوى محلي في Chrome يختلف عن المحتوى الذي يراه عند العرض عن بُعد، مع إمكانية التحكّم في هذه التجربة محليًا. تشمل الأمثلة إدارة قائمة انتظار التشغيل على youtube.com أثناء تشغيل الفيديوهات على التلفزيون أو مشاهدة مقتطفات فيديو تتضمّن ملاحظات المحاضر على كمبيوتر محمول أثناء عرض العرض التقديمي بملء الشاشة في جلسة Hangout.

هناك سيناريوهات قد يرغب المستخدمون فيها ببساطة في عرض المحتوى على شاشة مرفقة ثانية. على سبيل المثال، تخيل مستخدمًا في غرفة مؤتمرات مزود بجهاز عرض متصل به عبر كابل HDMI. بدلاً من النسخ المطابق للعرض التقديمي على نقطة نهاية بعيدة، فإن المستخدم يريد حقًا عرض الشرائح في وضع ملء الشاشة على جهاز العرض، مما يترك شاشة الكمبيوتر المحمول متاحة لملاحظات المحاضر والتحكم في الشرائح. وعلى الرغم من أنّ مؤلف الموقع الإلكتروني يمكنه إتاحة ذلك بطريقة أولية للغاية (على سبيل المثال، فتح نافذة جديدة يضطر المستخدم إلى سحبها يدويًا إلى الشاشة الثانوية وتكبيرها يدويًا إلى وضع ملء الشاشة)، فهو أمر مرهق ويقدّم تجربة غير متسقة بين العرض المحلي والعرض عن بُعد.

مشاركة عرض صفحة

سأشرح كيف يمكنك استخدام Presentation API لعرض صفحة ويب على الشاشة الثانوية المرفقة. تتوفّر النتيجة النهائية على https://googlechrome.github.io/samples/presentation-api/.

أولاً، سننشئ كائن PresentationRequest جديدًا يحتوي على عنوان URL الذي نريد عرضه على الشاشة الثانوية المرفقة.

const presentationRequest = new PresentationRequest('receiver.html');

In this article, I won’t cover use cases where the parameter passed to
`PresentationRequest` can be an array like `['cast://foo’, 'apple://foo',
'https://example.com']` as this is not relevant there.

We can now monitor presentation display availability and toggle a "Present"
button visibility based on presentation displays availability. Note that we can
also decide to always show this button.

<aside class="caution"><b>Caution:</b> The browser may use more energy while the <code>availability</code> object is alive
and actively listening for presentation display availability changes. Please
use it with caution in order to save energy on mobile.</aside>

```js
presentationRequest.getAvailability()
  .then(availability => {
    console.log('Available presentation displays: ' + availability.value);
    availability.addEventListener('change', function() {
      console.log('> Available presentation displays: ' + availability.value);
    });
  })
  .catch(error => {
    console.log('Presentation availability not supported, ' + error.name + ': ' +
        error.message);
  });

يتطلب إظهار إشعار عرض العرض التقديمي إيماءة مستخدم مثل النقر على زر. لذا دعنا نتصل بـ presentationRequest.start() بنقرة زر وننتظر أن يتم حلّ الوعد بعد أن يختار المستخدم عرض تقديمي (على سبيل المثال، شاشة ثانوية مرفقة في حالة الاستخدام لدينا).

function onPresentButtonClick() {
  presentationRequest.start()
  .then(connection => {
    console.log('Connected to ' + connection.url + ', id: ' + connection.id);
  })
  .catch(error => {
    console.log(error);
  });
}

وقد تتضمّن القائمة المعروضة للمستخدم أيضًا نقاط نهاية بعيدة، مثل أجهزة Chromecast في حال الاتصال بشبكة تعلن عنها. تجدر الإشارة إلى أنّ الشاشات التي تتم مزامنتها على الجهاز وفي السحابة الإلكترونية ليست مُدرَجة في القائمة. يمكنك الاطّلاع على http://crbug.com/840466.

منتقي عرض العروض التقديمية
أداة اختيار عرض العروض التقديمية

عند حلّ الوعد، يتم عرض صفحة الويب على عنوان URL للعنصر PresentationRequest في العرض الذي تم اختياره. حسنًا!

يمكننا الآن الانتقال بشكل أكبر ومراقبة أحداث "الإغلاق" و "الانتهاء" كما هو موضّح أدناه. يُرجى العِلم بأنّه يمكن إعادة الاتصال بالعنصر "presentationConnection" "المغلق" باستخدام presentationRequest.reconnect(presentationId)، حيث يكون presentationId هو رقم تعريف عنصر presentationRequest السابق.

function onCloseButtonClick() {
  // Disconnect presentation connection but will allow reconnection.
  presentationConnection.close();
}

presentationConnection.addEventListener('close', function() {
  console.log('Connection closed.');
});


function onTerminateButtonClick() {
  // Stop presentation connection for good.
  presentationConnection.terminate();
}

presentationConnection.addEventListener('terminate', function() {
  console.log('Connection terminated.');
});

التواصل مع الصفحة

هذا أمر رائع ولكن كيف أنقل الرسائل بين صفحة وحدة التحكّم (التي أنشأناها للتو) وصفحة المستلِم (الصفحة التي مررنا بها إلى عنصر PresentationRequest

أولاً، دعنا نسترد الاتصالات الحالية على صفحة جهاز الاستقبال باستخدام navigator.presentation.receiver.connectionList ونستمع إلى الاتصالات الواردة كما هو موضّح أدناه.

// Receiver page

navigator.presentation.receiver.connectionList
.then(list => {
  list.connections.map(connection => addConnection(connection));
  list.addEventListener('connectionavailable', function(event) {
    addConnection(event.connection);
  });
});

function addConnection(connection) {

  connection.addEventListener('message', function(event) {
    console.log('Message: ' + event.data);
    connection.send('Hey controller! I just received a message.');
  });

  connection.addEventListener('close', function(event) {
    console.log('Connection closed!', event.reason);
  });
}

يؤدي الاتصال لتلقّي رسالة إلى تنشيط حدث "رسالة" يمكنك الاستماع إليه. يمكن أن تكون الرسالة سلسلة أو Blob أو ArrayBuffer أو ArrayBufferView. يمكنك إرسال الرسالة ببساطة من خلال طلب الرقم connection.send(message) من صفحة وحدة التحكّم أو صفحة المستلِم.

// Controller page

function onSendMessageButtonClick() {
  presentationConnection.send('Hello!');
}

presentationConnection.addEventListener('message', function(event) {
  console.log('I just received ' + event.data + ' from the receiver.');
});

يمكنك تجربة النموذج على الرابط https://googlechrome.github.io/samples/presentation-api/ للتعرّف على آلية عملها. أنا متأكد من أنك ستستمتع بهذه التجربة بقدر ما استمتعتُ به.

العيّنات والعروض التوضيحية

يمكنك الاطّلاع على نموذج Chrome الرسمي الذي استخدمناه في هذه المقالة.

أنصحك أيضًا بالإصدار التجريبي التفاعلي من Photowall. يتيح تطبيق الويب هذا لوحدات تحكم متعددة تقديم عرض شرائح للصور بشكل تعاوني على شاشة عرض تقديمي. يتوفّر الرمز البرمجي على الرابط https://github.com/GoogleChromeLabs/presentation-api-samples.

لقطة شاشة للعرض التوضيحي لـ Photowall
صورة من إعداد "خوسيه لويس ميزا" / CC BY-NC-SA 2.0

هناك شيء آخر

يتضمّن Chrome قائمة متصفِّح "البثّ" التي يمكن للمستخدمين استدعاءها في أي وقت أثناء زيارة أي موقع إلكتروني. إذا أردت التحكّم في العرض التقديمي التلقائي لهذه القائمة، عليك تخصيص "navigator.presentation.defaultRequest" لعنصر presentationRequest مخصّص تم إنشاؤه سابقًا.

// Make this presentation the default one when using the "Cast" browser menu.
navigator.presentation.defaultRequest = presentationRequest;

نصائح لمطوّري البرامج

لفحص صفحة المُستلِم وتصحيح الأخطاء، انتقِل إلى صفحة chrome://inspect الداخلية واختَر "غير ذلك"، ثم انقر على رابط "فحص" بجانب عنوان URL المعروض حاليًا.

فحص صفحات مستلِم العرض التقديمي
فحص صفحات مستلِم العرض التقديمي

ننصحك أيضًا بالانتقال إلى صفحة chrome://media-router-internals الداخلية للاطّلاع على تفاصيل حول عمليات الاكتشاف/مدى التوفّر الداخلية.

الخطوات التالية

بدءًا من الإصدار 66 من Chrome، ستتوافق الأنظمة الأساسية مع أنظمة التشغيل ChromeOS وLinux وWindows. وسيتوفر دعم أجهزة Mac لاحقًا.

المراجِع