Créer votre application Web (Dialogflow)

Une application Web est l'interface utilisateur d'une action qui utilise Interactive Canvas. Vous pouvez utiliser les technologies Web existantes (HTML, CSS et JavaScript) pour concevoir et développer votre application Web. Dans la plupart des cas, Interactive Canvas peut afficher le contenu Web comme un navigateur, mais certaines restrictions sont appliquées afin de protéger la confidentialité et la sécurité des utilisateurs. Avant de commencer à concevoir votre interface utilisateur, tenez compte des principes de conception décrits dans la section Design guidelines.

Le code HTML et JavaScript de votre application Web effectue les opérations suivantes:

  • Enregistrez des callbacks d'événements Interactive Canvas.
  • Initialisez la bibliothèque JavaScript Interactive Canvas.
  • fournir une logique personnalisée pour mettre à jour votre application Web en fonction de l'état ;

Cette page présente les méthodes recommandées pour créer votre application Web, comment permettre la communication entre votre application Web et le traitement, ainsi que les consignes générales et les restrictions.

Bien que vous puissiez utiliser n'importe quelle méthode pour créer votre UI, Google vous recommande d'utiliser les bibliothèques suivantes:

Architecture

Google vous recommande vivement d'utiliser une architecture d'application monopage. Cette approche permet des performances optimales et assure une expérience utilisateur de conversation continue. Interactive Canvas peut être utilisé conjointement avec des frameworks front-end tels que Vue, Angular et React, qui facilitent la gestion des états.

Fichier HTML

Le fichier HTML définit l'apparence de votre interface utilisateur. Ce fichier charge également la bibliothèque JavaScript Interactive Canvas, qui permet la communication entre votre application Web et votre action de conversation.

<!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>

Communication entre le traitement et l'application Web

Maintenant que vous avez créé votre application Web et votre traitement, et que vous les avez chargées dans la bibliothèque Interactive Canvas dans le fichier de votre application Web, vous devez définir l'interaction entre votre application Web et le traitement. Pour ce faire, modifiez les fichiers contenant la logique de votre application Web.

action.js

Ce fichier contient le code permettant de définir des callbacks et d'appeler des méthodes via interactiveCanvas. Les rappels permettent à votre application Web de répondre aux informations ou aux requêtes provenant de l'action conversationnelle, tandis que les méthodes permettent d'envoyer des informations ou des requêtes à l'action de conversation.

Ajoutez interactiveCanvas.ready(callbacks); à votre fichier HTML pour initialiser et enregistrer des 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

Ce fichier construit la scène de votre application Web. Dans cet exemple, il gère également les cas de réussite et d'échec de la promesse renvoyée avec sendTextQuery(). Voici un extrait de 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;
});

Prise en charge des interactions tactiles

Votre action Interactive Canvas peut répondre à la pression du doigt de l'utilisateur ainsi qu'à ses saisies vocales. Conformément aux consignes de conception d'Interactive Canvas, vous devez développer votre action de sorte qu'elle soit "voice-first" (axée sur la voix). Cela dit, certains écrans intelligents acceptent les interactions tactiles.

La prise en charge du toucher est semblable à la prise en charge des réponses conversationnelles. Toutefois, au lieu d'une réponse vocale de l'utilisateur, votre code JavaScript côté client recherche les interactions tactiles et les utilise pour modifier les éléments de l'application Web.

Vous pouvez en voir un exemple dans l'exemple, qui utilise la bibliothèque 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;
});
...

Dans ce cas, la valeur de la variable spin est envoyée via l'API interactiveCanvas en tant que rappel update. Le traitement comporte une logique qui déclenche un intent en fonction de la valeur de spin.

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

Ajouter des fonctionnalités supplémentaires

Maintenant que vous avez appris les bases, vous pouvez améliorer et personnaliser votre action avec des API spécifiques à Canvas. Cette section explique comment implémenter ces API dans votre action Interactive Canvas.

sendTextQuery()

La méthode sendTextQuery() envoie des requêtes textuelles à l'action de conversation pour appeler un intent de manière programmatique. Cet exemple utilise sendTextQuery() pour redémarrer le jeu de rotation lorsque l'utilisateur clique sur un bouton. Lorsque l'utilisateur clique sur le bouton "Redémarrer le jeu", sendTextQuery() appelle l'intent Restart game et renvoie une promesse. Cette promesse génère SUCCESS si l'intent est déclenché et BLOCKED dans le cas contraire. L'extrait de code suivant déclenche l'intent et gère les cas de réussite et d'échec de la promesse:

//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}`);
      }
    });
...

Si la promesse aboutit à SUCCESS, l'intent Restart game envoie un HtmlResponse à votre application Web:

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

Cet HtmlResponse déclenche le rappel onUpdate(), qui exécute le code dans l'extrait de code RESTART_GAME ci-dessous:

//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()

Le rappel OnTtsMark() est appelé lorsque vous incluez une balise <mark> avec un nom unique dans la réponse SSML à l'utilisateur. Dans les extraits suivants de l'exemple Snowman, OnTtsMark() synchronise l'animation de l'application Web avec la sortie de synthèse vocale correspondante. Lorsque l'action indique à l'utilisateur Désolé, vous avez perdu, l'application Web épele le mot correct et affiche les lettres à l'utilisateur.

L'intent Game Over Reveal Word inclut une marque personnalisée dans la réponse envoyée à l'utilisateur lorsqu'il perd la partie:

//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());
});
...

L'extrait de code suivant enregistre ensuite le rappel OnTtsMark(), vérifie le nom de la marque et exécute la fonction revealCorrectWord(), qui met à jour l'application Web:

//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();
      }
    },
...

Restrictions

Tenez compte des restrictions suivantes lorsque vous développez votre application Web:

  • Aucun cookie
  • Pas de stockage local
  • Pas de géolocalisation
  • Aucune utilisation de l'appareil photo
  • Aucun pop-up
  • Ne pas dépasser la limite de mémoire de 200 Mo
  • L'en-tête tiers occupe la partie supérieure de l'écran
  • Aucun style ne peut être appliqué aux vidéos
  • Vous ne pouvez utiliser qu'un seul élément multimédia à la fois
  • Aucune vidéo HLS
  • Aucune base de données Web SQL
  • L'interface SpeechRecognition de l'API Web Speech n'est pas compatible.
  • Aucun enregistrement audio ou vidéo
  • Paramètre mode sombre non applicable

Partage des ressources entre origines multiples (CORS)

Étant donné que les applications Web Interactive Canvas sont hébergées dans un iFrame et que l'origine est définie sur "null", vous devez activer le partage des ressources entre origines multiples (CORS) pour vos serveurs Web et vos ressources de stockage. Cela permet à vos éléments d'accepter les requêtes provenant d'origines nulles.