Tạo ứng dụng web (Dialogflow)

Ứng dụng web là giao diện người dùng cho một Hành động sử dụng Canvas tương tác. Bạn có thể sử dụng các công nghệ web hiện có (HTML, CSS và JavaScript) để thiết kế và phát triển ứng dụng web. Đối với hầu hết các tính năng, Canvas tương tác có thể hiển thị nội dung web như một trình duyệt, nhưng có một vài hạn chế được thực thi đối với quyền riêng tư và bảo mật của người dùng. Trước khi bắt đầu thiết kế giao diện người dùng, hãy xem xét các nguyên tắc thiết kế được nêu trong mục Design guidelines.

HTML và JavaScript cho ứng dụng web của bạn thực hiện những việc sau:

  • Đăng ký callbacks sự kiện Canvas tương tác.
  • Khởi chạy thư viện JavaScript của Canvas tương tác.
  • Cung cấp logic tuỳ chỉnh để cập nhật ứng dụng web dựa trên trạng thái.

Trang này giới thiệu các cách được đề xuất để tạo ứng dụng web, cách cho phép giao tiếp giữa ứng dụng web và phương thức thực hiện, cũng như các nguyên tắc và hạn chế chung.

Mặc dù bạn có thể dùng bất kỳ phương thức nào để xây dựng giao diện người dùng, nhưng bạn nên sử dụng các thư viện sau:

Cấu trúc

Bạn nên sử dụng cấu trúc ứng dụng một trang. Phương pháp này mang lại hiệu suất tối ưu và hỗ trợ trải nghiệm người dùng trò chuyện liên tục. Bạn có thể sử dụng Canvas tương tác cùng với các khung giao diện người dùng như Vue, AngularReact để giúp quản lý trạng thái.

Tệp HTML

Tệp HTML xác định giao diện người dùng của bạn. Tệp này cũng tải thư viện JavaScript của Canvas tương tác, cho phép giao tiếp giữa ứng dụng web và Hành động trò chuyện.

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

Giao tiếp giữa phương thức thực hiện và ứng dụng web

Giờ đây, sau khi tạo ứng dụng web và phương thức thực hiện, bạn sẽ tải vào Thư viện Canvas tương tác trong tệp ứng dụng web, bạn cần xác định cách ứng dụng web và phương thức thực hiện tương tác. Để thực hiện việc này, hãy sửa đổi các tệp chứa logic của ứng dụng web.

action.js

Tệp này chứa mã để xác định callbacks và gọi các phương thức thông qua interactiveCanvas. Lệnh gọi lại cho phép ứng dụng web của bạn phản hồi thông tin hoặc yêu cầu từ Hành động trò chuyện, còn các phương thức cung cấp cách gửi thông tin hoặc yêu cầu đến Hành động trò chuyện đó.

Thêm interactiveCanvas.ready(callbacks); vào tệp HTML của bạn để khởi chạy và đăng ký 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

Tệp này sẽ tạo cảnh cho ứng dụng web của bạn. Trong ví dụ này, tệp này cũng xử lý các trường hợp thành công và không thành công của lời hứa được trả về bằng sendTextQuery(). Sau đây là một phần trích dẫn từ 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;
});

Hỗ trợ tương tác chạm

Thao tác Canvas tương tác có thể phản hồi thao tác chạm của người dùng cũng như phản hồi bằng giọng nói của họ. Theo Nguyên tắc thiết kế Canvas tương tác, bạn nên phát triển Hành động của mình theo cách "ưu tiên lên tiếng". Dù vậy, một số màn hình thông minh hỗ trợ các tương tác chạm.

Thao tác chạm hỗ trợ cũng tương tự như việc hỗ trợ phản hồi trò chuyện. Tuy nhiên, thay vì phản hồi bằng giọng nói của người dùng, JavaScript phía máy khách của bạn sẽ tìm các tương tác chạm và sử dụng các tương tác đó để thay đổi các thành phần trong ứng dụng web.

Bạn có thể xem ví dụ về cách này trong mẫu sử dụng thư viện 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;
});
...

Trong trường hợp này, giá trị của biến spin sẽ được gửi qua API interactiveCanvas dưới dạng lệnh gọi lại update. Phương thức thực hiện có logic kích hoạt ý định dựa trên giá trị của spin.

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

Thêm tính năng khác

Giờ đây, khi đã tìm hiểu kiến thức cơ bản, bạn có thể cải thiện và tuỳ chỉnh Hành động của mình bằng các API dành riêng cho Canvas. Phần này giải thích cách triển khai các API này trong Thao tác Canvas tương tác.

sendTextQuery()

Phương thức sendTextQuery() gửi truy vấn văn bản đến Hành động trò chuyện để gọi một ý định theo phương thức lập trình. Mẫu này sử dụng sendTextQuery() để bắt đầu lại trò chơi quay hình tam giác khi người dùng nhấp vào một nút. Khi người dùng nhấp vào nút "Khởi động lại trò chơi", sendTextQuery() sẽ gọi ý định Restart game và trả về một lời hứa. Lời hứa này sẽ dẫn đến SUCCESS nếu ý định được kích hoạt và BLOCKED nếu ý định không được kích hoạt. Đoạn mã sau đây kích hoạt ý định và xử lý các trường hợp thành công và thất bại của lời hứa:

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

Nếu lời hứa dẫn đến SUCCESS, ý định Restart game sẽ gửi HtmlResponse đến ứng dụng web của bạn:

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

HtmlResponse này kích hoạt lệnh gọi lại onUpdate(), thực thi mã trong đoạn mã RESTART_GAME dưới đây:

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

Lệnh gọi lại OnTtsMark() được gọi khi bạn đưa một thẻ <mark> có tên riêng biệt vào phản hồi SSML cho người dùng. Trong các phần trích dẫn sau đây từ mẫu Người tuyết, OnTtsMark() sẽ đồng bộ hoá ảnh động của ứng dụng web với đầu ra TTS tương ứng. Khi Hành động đã thông báo với người dùng Rất tiếc, bạn đã mất, ứng dụng web sẽ đọc từ chính xác và hiển thị các chữ cái cho người dùng.

Ý định Game Over Reveal Word bao gồm một nhãn tuỳ chỉnh trong phản hồi cho người dùng khi họ thua trò chơi:

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

Sau đó, đoạn mã sau đây sẽ đăng ký lệnh gọi lại OnTtsMark(), kiểm tra tên của nhãn và thực thi hàm revealCorrectWord() nhằm cập nhật ứng dụng 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();
      }
    },
...

Quy định hạn chế

Hãy cân nhắc các hạn chế sau khi bạn phát triển ứng dụng web của mình:

  • Không có cookie
  • Không có bộ nhớ cục bộ
  • Không có vị trí địa lý
  • Không sử dụng máy ảnh
  • Không có cửa sổ bật lên
  • Giữ dưới giới hạn bộ nhớ 200 MB
  • Tiêu đề của bên thứ ba chiếm phần trên của màn hình
  • Không thể áp dụng kiểu nào cho video
  • Mỗi lần chỉ có thể sử dụng một phần tử nội dung nghe nhìn
  • Không có video HLS
  • Không có cơ sở dữ liệu Web SQL
  • Không hỗ trợ giao diện SpeechRecognition của Web Speech API.
  • Không có bản ghi âm thanh hoặc video
  • Không áp dụng được chế độ cài đặt chế độ tối

Chia sẻ tài nguyên trên nhiều nguồn gốc

Vì các ứng dụng web Canvas tương tác được lưu trữ trong một iframe và nguồn gốc được đặt thành rỗng, nên bạn phải bật tính năng chia sẻ tài nguyên trên nhiều nguồn gốc (CORS) cho máy chủ web và tài nguyên lưu trữ của mình. Điều này cho phép tài sản của bạn chấp nhận các yêu cầu từ các nguồn gốc rỗng.