Webanwendung erstellen (Dialogflow)

Eine Webanwendung ist die Benutzeroberfläche für eine Aktion, die den interaktiven Canvas verwendet. Sie können vorhandene Webtechnologien (HTML, CSS und JavaScript) für den Entwurf und die Entwicklung Ihrer Webanwendung verwenden. In den meisten Fällen können Sie mit Interactive Canvas Webinhalte wie in einem Browser rendern. Allerdings gelten für den Datenschutz und die Sicherheit einige Einschränkungen. Bevor Sie mit dem Entwerfen der UI beginnen, sollten Sie sich die im Abschnitt Design guidelines beschriebenen Designprinzipien ansehen.

Der HTML- und JavaScript-Code für Ihre Webanwendung führen folgende Schritte aus:

  • Registrieren Sie callbacks für das Interactive Canvas-Ereignis.
  • Initialisieren Sie die Interactive Canvas JavaScript-Bibliothek.
  • Geben Sie eine benutzerdefinierte Logik zum Aktualisieren Ihrer Web-App basierend auf dem Status an.

Auf dieser Seite werden die empfohlenen Methoden zum Erstellen einer Webanwendung, die Kommunikation zwischen der Webanwendung und der Auftragsausführung sowie allgemeine Richtlinien und Einschränkungen erläutert.

Sie können jede Methode zum Erstellen Ihrer UI verwenden. Google empfiehlt jedoch die folgenden Bibliotheken:

Architektur

Google empfiehlt dringend, eine Single-Page-Anwendungsarchitektur zu verwenden. Dieser Ansatz ermöglicht eine optimale Leistung und unterstützt eine kontinuierliche Konversation für Nutzer. Interactive Canvas kann in Verbindung mit Front-End-Frameworks wie Vue, Angular und React verwendet werden, die die Statusverwaltung vereinfachen.

HTML-Datei

Die HTML-Datei definiert, wie Ihre Benutzeroberfläche aussieht. Mit dieser Datei wird auch die Interactive Canvas JavaScript-Bibliothek geladen, die die Kommunikation zwischen Ihrer Webanwendung und der konversationellen Aktion ermöglicht.

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

Kommunikation zwischen Auftragsausführung und Webanwendung

Nachdem Sie Ihre Webanwendung und die Auftragsausführung erstellt und in die Webanwendungsdatei in der interaktiven Canvas-Bibliothek geladen haben, müssen Sie festlegen, wie Ihre Webanwendung und die Auftragsausführung interagieren. Ändern Sie dazu die Dateien, die die Logik Ihrer Webanwendung enthalten.

action.js

Diese Datei enthält den Code zum Definieren von callbacks und zum Aufrufen von Methoden über interactiveCanvas. Callbacks ermöglichen es der Webanwendung, auf Informationen oder Anfragen von der dialogorientierten Aktion zu antworten. Methoden bieten eine Möglichkeit, Informationen oder Anfragen an die dialogorientierte Aktion zu senden.

Fügen Sie der HTML-Datei interactiveCanvas.ready(callbacks); hinzu, um callbacks zu initialisieren und zu registrieren:

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

Diese Datei erstellt die Szene für Ihre Webanwendung. In diesem Beispiel werden auch die Erfolgs- und Fehlerfälle des Promise-Objekts verarbeitet, das mit sendTextQuery() zurückgegeben wurde. Das ist ein Auszug aus 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;
});

Touch-Interaktionen unterstützen

Die Interactive Canvas Action kann sowohl auf Berührungen als auch auf Gesangseingaben des Nutzers reagieren. Gemäß den Designrichtlinien für Interactive Canvas solltest du deine Aktion so programmieren, dass sie sprachorientiert ist. Einige Smart Displays unterstützen Touch-Interaktionen.

Eine unterstützende Berührung ist mit der Unterstützung von Konversationsantworten vergleichbar. Statt einer gesprochenen Antwort des Nutzers sucht Ihr clientseitiges JavaScript jedoch nach Touch-Interaktionen und verwendet diese, um Elemente in der Webanwendung zu ändern.

Ein Beispiel dafür finden Sie im Beispiel, in dem die Pixi.js verwendet wird:

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

In diesem Fall wird der Wert der Variable spin über die interactiveCanvas API als update-Callback gesendet. Die Auftragsausführung hat eine Logik, die einen Intent basierend auf dem Wert von spin auslöst.

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

Weitere Funktionen hinzufügen

Nachdem du jetzt mit den Grundlagen vertraut bist, kannst du deine Aktion mit Canvas-spezifischen APIs optimieren und anpassen. In diesem Abschnitt wird erläutert, wie Sie diese APIs in Ihrer Interactive Canvas Action implementieren.

sendTextQuery()

Die Methode sendTextQuery() sendet Textabfragen an die dialogorientierte Aktion, um einen Intent programmatisch aufzurufen. In diesem Beispiel wird sendTextQuery() verwendet, um das sich drehende Spiel neu zu starten, wenn der Nutzer auf eine Schaltfläche klickt. Wenn der Nutzer auf die Schaltfläche „Spiel neu starten“ klickt, ruft sendTextQuery() den Intent Restart game auf und gibt ein Versprechen zurück. Dieses Versprechen führt zu SUCCESS, wenn der Intent ausgelöst wird, und zu BLOCKED, wenn dies nicht der Fall ist. Das folgende Snippet löst den Intent aus und verarbeitet die Erfolgs- und Fehlerfälle des Promise:

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

Wenn das Promise SUCCESS ergibt, sendet der Intent Restart game ein HtmlResponse an Ihre Webanwendung:

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

Diese HtmlResponse löst den onUpdate()-Callback aus, der den Code im folgenden RESTART_GAME-Code-Snippet ausführt:

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

Der OnTtsMark()-Callback wird aufgerufen, wenn Sie in die SSML-Antwort an den Nutzer ein <mark>-Tag mit einem eindeutigen Namen einfügen. In den folgenden Auszügen aus dem Snowman-Beispiel synchronisiert OnTtsMark() die Animation der Webanwendung mit der entsprechenden TTS-Ausgabe. Wenn die Aktion zum Nutzer Du hast leider verloren gesagt hat, buchstabiert die Web-App das richtige Wort und zeigt dem Nutzer die Buchstaben an.

Der Intent Game Over Reveal Word enthält eine benutzerdefinierte Markierung in der Antwort an den Nutzer, wenn er das Spiel verloren hat:

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

Mit dem folgenden Code-Snippet wird dann der OnTtsMark()-Callback registriert, der Name der Marke geprüft und die Funktion revealCorrectWord() ausgeführt, mit der die Webanwendung aktualisiert wird:

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

Einschränkungen

Berücksichtigen Sie bei der Entwicklung Ihrer Webanwendung die folgenden Einschränkungen:

  • Keine Cookies
  • Kein lokaler Speicher
  • Keine Standortbestimmung
  • Keine Kameranutzung
  • Keine Pop-ups
  • Unter dem Arbeitsspeicherlimit von 200 MB bleiben
  • Drittanbieter-Header nimmt den oberen Teil des Bildschirms ein
  • Auf Videos können keine Stile angewendet werden
  • Es kann jeweils nur ein Medienelement verwendet werden
  • Kein HLS-Video
  • Keine Web SQL-Datenbank
  • Keine Unterstützung für die SpeechRecognition-Schnittstelle der Web Speech API.
  • Keine Audio- oder Videoaufzeichnung
  • Dunkler Modus nicht anwendbar

Cross-Origin Resource Sharing

Da Interactive Canvas-Webanwendungen in einem iFrame gehostet werden und der Ursprung auf null gesetzt ist, müssen Sie das Cross-Origin Resource Sharing (CORS) für Ihre Webserver und Speicherressourcen aktivieren. So können Ihre Assets Anfragen von Null-Ursprüngen akzeptieren.