إنشاء تطبيق الويب (Dialogflow)

تطبيق الويب هو واجهة مستخدم لإجراء يستخدم "لوحة الرسم التفاعلية". يمكنك استخدام تقنيات الويب الحالية (HTML وCSS وJavaScript) لتصميم تطبيق الويب وتطويره. وفي معظم الأحيان، تستطيع لعبة Interactive Canvas عرض محتوى الويب بشكل مشابه للمتصفح، ولكن هناك بعض القيود المفروضة على خصوصية المستخدم وأمانه. قبل البدء في تصميم واجهة المستخدم، يجب مراعاة مبادئ التصميم الموضّحة في القسم Design guidelines.

ينفذ كل من HTML وJavaScript لتطبيق الويب ما يلي:

  • تسجيل callbacks في حدث "لوحة الرسم التفاعلية"
  • تهيئة مكتبة JavaScript للوحة الرسم التفاعلية.
  • قدِّم منطقًا مخصَّصًا لتحديث تطبيق الويب استنادًا إلى الحالة.

تتناول هذه الصفحة الطرق الموصى بها لإنشاء تطبيق الويب، وكيفية تمكين التواصل بين تطبيق الويب وتنفيذه، والإرشادات والقيود العامة.

على الرغم من أنّه يمكنك استخدام أي طريقة لإنشاء واجهة المستخدم، تنصح Google باستخدام المكتبات التالية:

  • Greensock: لإنشاء صور متحركة معقدة.
  • Pixi.js: لرسم رسومات ثنائية الأبعاد على WebGL
  • Three.js: لرسم رسومات ثلاثية الأبعاد على WebGL.
  • رسم لوحة HTML5: للحصول على رسومات بسيطة.
  • عنصر DOM: للمحتوى الثابت.

هندسة معمارية

تنصح Google بشدة باستخدام بنية تطبيق من صفحة واحدة. يسمح هذا النهج بالأداء الأمثل ويدعم تجربة المستخدم الحوارية المستمرة. يمكن استخدام لوحة الرسم التفاعلية إلى جانب إطارات عمل الواجهة الأمامية، مثل Vue وAngular وReact التي تساعد في إدارة الحالة.

ملف HTML

يحدّد ملف HTML مظهر واجهة المستخدم. يُحمِّل هذا الملف أيضًا مكتبة JavaScript للوحة الرسم التفاعلية، والتي تتيح التواصل بين تطبيق الويب والإجراء الحواري.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Immersive Canvas Sample</title>
    <!-- Disable favicon requests -->
    <link rel="shortcut icon" type="image/x-icon" href="data:image/x-icon;,">
    <!-- Load Interactive Canvas JavaScript -->
    <script src="https://www.gstatic.com/assistant/df-asdk/interactivecanvas/api/interactive_canvas.min.js"></script>
    <!-- Load PixiJS for graphics rendering -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.8.7/pixi.min.js"></script>
    <!-- Load Stats.js for fps monitoring -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/stats.js/r16/Stats.min.js"></script>
    <!-- Load custom CSS -->
    <link rel="stylesheet" href="css/main.css">
  </head>
  <body>
    <div id="view" class="view">
      <div class="debug">
        <div class="stats"></div>
        <div class="logs"></div>
      </div>
    </div>
    <!-- Load custom JavaScript after elements are on page -->
    <script src="js/main.js"></script>
    <script src="js/log.js"></script>
  </body>
</html>

التواصل بين توفير الطلبات وتطبيق الويب

الآن بعد أن أنشأت تطبيق الويب وتنفيذه وتم تحميله في مكتبة لوحة الرسم التفاعلية في ملف تطبيق الويب، يجب تحديد كيفية تفاعل تطبيق الويب مع عملية التنفيذ. للقيام بذلك، قم بتعديل الملفات التي تحتوي على منطق تطبيق الويب الخاص بك.

action.js

يحتوي هذا الملف على الرمز البرمجي لتحديد callbacks واستدعاء طرق من خلال interactiveCanvas. تسمح عمليات معاودة الاتصال لتطبيق الويب الخاص بك بالردّ على المعلومات أو الطلبات من "الإجراء الحواري"، بينما توفّر الطرق طريقة لإرسال معلومات أو طلبات إلى "الإجراء الحواري".

أضِف interactiveCanvas.ready(callbacks); إلى ملف HTML لتهيئة callbacks وتسجيلها:

//action.js
class Action {
  constructor(scene) {
    this.canvas = window.interactiveCanvas;
    this.scene = scene;
    const that = this;
    this.commands = {
      TINT: function(data) {
        that.scene.sprite.tint = data.tint;
      },
      SPIN: function(data) {
        that.scene.sprite.spin = data.spin;
      },
      RESTART_GAME: function(data) {
        that.scene.button.texture = that.scene.button.textureButton;
        that.scene.sprite.spin = true;
        that.scene.sprite.tint = 0x0000FF; // blue
        that.scene.sprite.rotation = 0;
      },
    };
  }

  /**
   * Register all callbacks used by Interactive Canvas
   * executed during scene creation time.
   *
   */
  setCallbacks() {
    const that = this;
    // declare interactive canvas callbacks
    const callbacks = {
      onUpdate(data) {
        try {
          that.commands[data.command.toUpperCase()](data);
        } catch (e) {
          // do nothing, when no command is sent or found
        }
      },
    };
    // called by the Interactive Canvas web app once web app has loaded to
    // register callbacks
    this.canvas.ready(callbacks);
  }
}

main.js

ينشئ هذا الملف المشهد لتطبيق الويب. في هذا المثال، يتناول أيضًا حالات النجاح والفشل للوعد الذي يتم عرضه مع sendTextQuery(). وفي ما يلي مقتطف من main.js:

// main.js
const view = document.getElementById('view');
// initialize rendering and set correct sizing
this.renderer = PIXI.autoDetectRenderer({
  transparent: true,
  antialias: true,
  resolution: this.radio,
  width: view.clientWidth,
  height: view.clientHeight,
});
view.appendChild(this.element);

// center stage and normalize scaling for all resolutions
this.stage = new PIXI.Container();
this.stage.position.set(view.clientWidth / 2, view.clientHeight / 2);
this.stage.scale.set(Math.max(this.renderer.width,
    this.renderer.height) / 1024);

// load a sprite from a svg file
this.sprite = PIXI.Sprite.from('triangle.svg');
this.sprite.anchor.set(0.5);
this.sprite.tint = 0x00FF00; // green
this.sprite.spin = true;
this.stage.addChild(this.sprite);

// toggle spin on touch events of the triangle
this.sprite.interactive = true;
this.sprite.buttonMode = true;
this.sprite.on('pointerdown', () => {
  this.sprite.spin = !this.sprite.spin;
});

دعم التفاعلات باللمس

يمكن أن يستجيب إجراء لوحة الرسم التفاعلي الخاص بك إلى لمسة المستخدم ومدخلاته الصوتية. وفقًا لإرشادات تصميم "لوحة الرسم التفاعلية"، يجب تطوير الإجراء الخاص بك ليكون "إعطاء الأولوية للصوت". مع ذلك، تتيح بعض الشاشات الذكية إمكانية التفاعل باللمس.

يشبه لمس الدعم دعم الردود الحوارية؛ ومع ذلك، بدلاً من الرد الصوتي من المستخدم، تبحث لغة JavaScript من جهة العميل عن التفاعلات التي تتم باللمس وتستخدمها لتغيير العناصر في تطبيق الويب.

يمكنك الاطلاع على مثال لذلك في النموذج الذي يستخدم مكتبة Pixi.js:

...
this.sprite = PIXI.Sprite.from('triangle.svg');
...
this.sprite.interactive = true; // Enables interaction events
this.sprite.buttonMode = true; // Changes `cursor` property to `pointer` for PointerEvent
this.sprite.on('pointerdown', () => {
  this.sprite.spin = !this.sprite.spin;
});
...

في هذه الحالة، يتم إرسال قيمة المتغيّر spin من خلال واجهة برمجة التطبيقات interactiveCanvas API كاستدعاء update. يحتوي التنفيذ على منطق يؤدي إلى تشغيل هدف استنادًا إلى قيمة spin.

...
app.intent('pause', (conv) => {
  conv.ask(`Ok, I paused spinning. What else?`);
  conv.ask(new HtmlResponse({
    data: {
      spin: false,
    },
  }));
});
...

إضافة المزيد من الميزات

بعد أن تعلمت الأساسيات، يمكنك تحسين الإجراء الخاص بك وتخصيصه باستخدام واجهات برمجة التطبيقات الخاصة بلوحة الرسم. يشرح هذا القسم كيفية تنفيذ واجهات برمجة التطبيقات في "إجراء لوحة الرسم التفاعلي".

sendTextQuery()

ترسل الطريقة sendTextQuery() طلبات بحث نصية إلى "الإجراء الحواري" لاستدعاء هدف برمجيًا. يستخدم هذا النموذج sendTextQuery() لإعادة تشغيل لعبة الدوران المثلثي عندما ينقر المستخدم على زر. عندما ينقر المستخدم على زر "إعادة تشغيل اللعبة"، يستدعي sendTextQuery() هدف Restart game ويعرض وعدًا. ينتج عن هذا الوعد SUCCESS إذا تم تفعيل الهدف وBLOCKED إذا لم يكن كذلك. يؤدي المقتطف التالي إلى تشغيل النية ويتناول حالات النجاح والفشل للوعد:

//main.js
...
that.action.canvas.sendTextQuery('Restart game')
    .then((res) => {
      if (res.toUpperCase() === 'SUCCESS') {
        console.log(`Request in flight: ${res}`);
        that.button.texture = that.button.textureButtonDisabled;
        that.sprite.spin = false;
      } else {
        console.log(`Request in flight: ${res}`);
      }
    });
...

إذا نتج عن الوعد SUCCESS، يرسل الغرض Restart game HtmlResponse إلى تطبيق الويب:

//index.js
...
app.intent('restart game', (conv) => {
  conv.ask(new HtmlResponse({
    data: {
      command: 'RESTART_GAME',
    },
...

يؤدي HtmlResponse هذا إلى تشغيل استدعاء onUpdate()، الذي ينفِّذ الرمز في مقتطف الرمز RESTART_GAME أدناه:

//action.js
...
RESTART_GAME: function(data) {
  that.scene.button.texture = that.scene.button.textureButton;
  that.scene.sprite.spin = true;
  that.scene.sprite.tint = 0x0000FF; // blue
  that.scene.sprite.rotation = 0;
},
...

OnTtsMark()

يتم استدعاء استدعاء OnTtsMark() عند تضمين علامة <mark> باسم فريد في رد SSML إلى المستخدم. في المقتطفات التالية من عينة Snowman، يعمل OnTtsMark() على مزامنة الصورة المتحركة لتطبيق الويب مع مخرجات تقنية تحويل النص إلى كلام (TTS) المقابلة. عندما يقول الإجراء للمستخدم عذرًا، لقد فقدت، يقوم تطبيق الويب بتهجئة الكلمة الصحيحة ويعرض الحروف للمستخدم.

يتضمن الغرض Game Over Reveal Word علامة مخصّصة في الردّ على المستخدم عند فقدان اللعبة:

//index.js
...
app.intent('Game Over Reveal Word', (conv, {word}) => {
  conv.ask(`<speak>Sorry, you lost.<mark name="REVEAL_WORD"/> The word is ${word}.` +
    `${PLAY_AGAIN_INSTRUCTIONS}</speak>`);
  conv.ask(new HtmlResponse());
});
...

بعد ذلك، يسجِّل مقتطف الرمز التالي استدعاء OnTtsMark()، ويتحقّق من اسم العلامة، وينفّذ دالة revealCorrectWord() التي تحدّث تطبيق الويب:

//action.js
...
setCallbacks() {
  const that = this;
  // declare assistant canvas action callbacks
  const callbacks = {
    onTtsMark(markName) {
      if (markName === 'REVEAL_WORD') {
        // display the correct word to the user
        that.revealCorrectWord();
      }
    },
...

القيود

ضع القيود التالية في الاعتبار عند تطوير تطبيق الويب:

  • ما مِن ملفات تعريف ارتباط
  • لا تتوفّر مساحة تخزين محلية
  • لا يوجد رصد الموقع الجغرافي
  • ما مِن استخدام للكاميرا
  • ما مِن نوافذ منبثقة
  • يجب ألا يزيد حجم الذاكرة عن 200 ميغابايت.
  • يشغل عنوان جهة خارجية الجزء العلوي من الشاشة
  • لا يمكن تطبيق أي أنماط على الفيديوهات.
  • يمكن استخدام عنصر وسائط واحد فقط في كل مرة
  • لا يتوفّر فيديو HLS
  • لا تتوفّر قاعدة بيانات لغة الاستعلامات البنيوية (SQL) على الويب
  • لا يتم دعم واجهة SpeechRecognition لواجهة برمجة تطبيقات Web Speech.
  • لا يتوفّر تسجيل صوت أو فيديو.
  • إعداد الوضع الداكن غير سارٍ

مشاركة الموارد المشتركة المصدر

نظرًا لأنّ تطبيقات الويب للوحة الرسم التفاعلية مستضافة في إطار iframe وتم ضبط المصدر على قيمة فارغة، عليك تفعيل مشاركة الموارد المتعدّدة المصادر (CORS) لخوادم الويب وموارد مساحة التخزين. يتيح ذلك لمواد العرض قبول الطلبات من المصادر الفارغة.