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

François Beaufort
François Beaufort

يسمح Chrome 66 لصفحات الويب باستخدام شاشة عرض مُرفقة ثانوية من خلال Presentation API والتحكّم في محتواها من خلال Presentation Receiver 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.

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

هناك شيء آخر

يتضمن Chrome قائمة متصفح "Cast" يمكن للمستخدمين استدعاؤها في أي وقت أثناء زيارة موقع إلكتروني. إذا أردت التحكّم في العرض التقديمي التلقائي لهذه القائمة، عليك ضبط 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 الداخلية للتعرّف على تفاصيل عمليات الاكتشاف/مدى التوفّر الداخلية.

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

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

المراجع