Tworzenie aplikacji internetowej (Dialogflow)

Aplikacja internetowa to interfejs akcji, która korzysta z interaktywnego obszaru roboczego. Do projektowania i tworzenia aplikacji możesz użyć istniejących technologii internetowych (HTML, CSS i JavaScript). W większości przypadków Interactive Canvas może renderować treści internetowe tak jak przeglądarka, ale obowiązują pewne ograniczenia związane z ochroną prywatności i bezpieczeństwem użytkownika. Zanim zaczniesz projektować interfejs, weź pod uwagę zasady projektowania opisane w sekcji Design guidelines.

Kody HTML i JavaScript Twojej aplikacji internetowej:

  • Zarejestruj callbacks zdarzenia Interactive Canvas.
  • Zainicjuj bibliotekę JavaScript Interactive Canvas.
  • Podaj niestandardowe zasady aktualizowania aplikacji internetowej na podstawie stanu.

Na tej stronie omawiamy zalecane sposoby tworzenia aplikacji internetowej, ułatwianie komunikacji między aplikacją internetową a jej realizacją oraz ogólne wytyczne i ograniczenia.

Możesz użyć dowolnej metody do utworzenia UI, ale Google zaleca używanie tych bibliotek:

Architektura

Google zdecydowanie zaleca stosowanie architektury aplikacji jednostronicowej. Takie podejście zapewnia optymalną wydajność i umożliwia ciągłe rozmowy z użytkownikiem. Interaktywnej aplikacji Canvas można używać w połączeniu ze platformami frontendowymi, takimi jak Vue, Angular i React, które ułatwiają zarządzanie stanami.

Plik HTML

Plik HTML definiuje wygląd interfejsu użytkownika. Ten plik wczytuje też interaktywną bibliotekę JavaScript Canvas, która umożliwia komunikację między aplikacją internetową a akcją konwersacyjną.

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

Komunikacja między realizacją a aplikacją internetową

Po utworzeniu aplikacji internetowej i realizacji zamówień oraz wczytaniu jej do interaktywnej biblioteki Canvas w pliku aplikacji internetowej musisz określić sposób interakcji między aplikacją internetową a realizacją. W tym celu zmodyfikuj pliki zawierające logikę aplikacji internetowej.

action.js

Ten plik zawiera kod do definiowania callbacks i wywoływania metod za pomocą interactiveCanvas. Wywołania zwrotne pozwalają aplikacji internetowej odpowiadać na informacje lub żądania z akcji konwersacyjnej, natomiast metody umożliwiają wysyłanie informacji lub żądań do akcji konwersacyjnej.

Dodaj interactiveCanvas.ready(callbacks); do pliku HTML, aby zainicjować i zarejestrować 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

Ten plik tworzy scenę dla aplikacji internetowej. W tym przykładzie obsługuje też przypadki powodzenia i niepowodzenia obiecującej obietnicy zwróconej za pomocą funkcji sendTextQuery(). Oto fragment z kursu 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;
});

Obsługa dotykowa

Działanie interaktywnego obszaru roboczego może reagować na dotyk użytkownika i jego głos. Zgodnie ze wskazówkami dotyczącymi projektowania interaktywnego obszaru roboczego akcja powinna być ukierunkowana na głos. Niektóre inteligentne ekrany obsługują interakcje dotykowe.

Obsługa dotyku jest podobna do obsługi reakcji konwersacyjnych. Jednak zamiast odpowiedzi głosowej użytkownika, skrypt JavaScript po stronie klienta wyszukuje interakcje dotykowe i wykorzystuje je do zmiany elementów aplikacji internetowej.

Przykład znajdziesz w przykładzie, który korzysta z biblioteki 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;
});
...

W tym przypadku wartość zmiennej spin jest przesyłana przez interfejs API interactiveCanvas jako wywołanie zwrotne update. Realizacja zawiera funkcje logiczne, które wyzwalają intencję na podstawie wartości spin.

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

Dodaj więcej funkcji

Gdy znasz już podstawy, możesz ulepszyć i dostosować akcję za pomocą interfejsów API Canvas. Z tej sekcji dowiesz się, jak wdrożyć te interfejsy API w działaniu Interactive Canvas.

sendTextQuery()

Metoda sendTextQuery() wysyła zapytania tekstowe do akcji konwersacyjnej, aby programowo wywołać intencję. W tym przykładzie użyto polecenia sendTextQuery(), aby ponownie uruchomić grę z trójkątami, gdy użytkownik kliknie przycisk. Gdy użytkownik kliknie przycisk „Uruchom ponownie grę”, sendTextQuery() wywołuje intencję Restart game i zwraca obietnicę. Ta obietnica daje SUCCESS, jeśli intencja jest wywołana, lub BLOCKED, jeśli nie jest. Ten fragment kodu aktywuje intencję i obsługuje przypadki powodzenia i niepowodzenia obietnicy:

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

Jeśli obietnica daje wynik SUCCESS, intencja Restart game wysyła HtmlResponse do Twojej aplikacji internetowej:

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

Ten element HtmlResponse uruchamia wywołanie zwrotne onUpdate(), które wykonuje kod z poniższego fragmentu kodu 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()

Wywołanie zwrotne OnTtsMark() jest wywoływane, gdy w odpowiedzi SSML kierowanej do użytkownika umieścisz tag <mark> o niepowtarzalnej nazwie. W poniższych fragmentach z przykładu Snowman OnTtsMark() synchronizuje animację aplikacji internetowej z odpowiednimi danymi wyjściowymi zamiany tekstu na mowę. Gdy akcja powie do użytkownika Niestety, przegrana, aplikacja internetowa przeliteruje właściwe słowo i wyświetla użytkownikowi litery.

Intencja Game Over Reveal Word zawiera niestandardowy znak w odpowiedzi dla użytkownika, który przegrał grę:

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

Ten fragment kodu rejestruje następnie wywołanie zwrotne OnTtsMark(), sprawdza nazwę znaku i wykonuje funkcję revealCorrectWord(), która aktualizuje aplikację internetową:

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

Ograniczenia

Podczas tworzenia aplikacji internetowej weź pod uwagę te ograniczenia:

  • Brak plików cookie
  • Brak pamięci lokalnej
  • Brak geolokalizacji
  • Brak użycia kamery
  • Brak wyskakujących okienek
  • Nie przekraczaj limitu 200 MB pamięci
  • Nagłówek innej firmy zajmuje górną część ekranu
  • Do filmów nie można zastosować żadnych stylów
  • W danym momencie można używać tylko jednego elementu multimedialnego
  • Brak obrazu HLS
  • Brak bazy danych Web SQL
  • Brak obsługi interfejsu SpeechRecognition interfejsu Web Speech API.
  • Brak nagrań dźwięku i obrazu
  • Nie można zastosować ustawienia trybu ciemnego

Udostępnianie zasobów między domenami

Ponieważ aplikacje internetowe interaktywnej aplikacji Canvas są hostowane w elemencie iframe, a źródło ma wartość null, musisz włączyć udostępnianie zasobów między domenami (CORS) dla swoich serwerów WWW i zasobów pamięci. Dzięki temu zasoby będą przyjmować żądania z źródeł o wartości null.