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 của bạn. Trong hầu hết trường hợp, Canvas tương tác có thể hiển thị nội dung web như 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 cân nhắc nguyên tắc thiết kế được nêu trong Design guidelines .

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

  • Đăng ký lệnh gọi lại sự kiện Canvas tương tác.
  • Khởi chạy thư viện JavaScript tương tác Canvas.
  • 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 đề xuất để xây dựng ứng dụng web của bạn, cách bật hoạt động 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 chung và hạn chế.

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

Kiến trúc

Bạn nên sử dụng cấu trúc ứng dụng trang đơn. Phương pháp này mang lại hiệu suất tối ưu và hỗ trợ trải nghiệm trò chuyện của người dùng. Canvas tương tác có thể được sử dụng cùng với các khung giao diện người dùng như Vue, GócPhản ứng, để 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 trang báo cáo Tương tác Thư viện JavaScript Canvas, hỗ trợ 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

Lúc này, bạn đã tạo xong ứng dụng web và phương thức thực hiện, đồng thời đã tải ứng dụng Tương tác Thư viện Canvas trong ứ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. Người nhận để thực hiện việc này, hãy sửa đổi các tệp chứa logic ứng dụng web của bạn.

action.js

Tệp này chứa mã để xác định lệnh gọi lại và gọi 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, trong khi các phương thức cung cấp phương thức 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 để khởi chạy và đăng ký lệnh gọi lại:

//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 tạo cảnh cho ứng dụng web của bạn. Trong ví dụ này, thẻ 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(). Chiến lược phát hành đĩa đơn 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 trên Canvas tương tác có thể phản hồi lại thao tác chạm của người dùng cũng như âm thanh đầu vào. 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 thành "ưu tiên giọng nói". Dù vậy, một số chiến dịch Thông minh Màn hình hỗ trợ tương tác chạm.

Việc hỗ trợ thao tác chạm cũng tương tự như việc hỗ trợ phản hồi khi 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 sẽ có giao diện cho 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ề điều này trong mẫu, sử dụng phương thức 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 được gửi thông qua API interactiveCanvas làm lệnh gọi lại update. Phương thức thực hiện có logic kích hoạt mộ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, sau khi đã tìm hiểu kiến thức cơ bản, bạn có thể nâng cao 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 Interactive Canvas Action (Thao tác trên vải canvas tương tác).

sendTextQuery()

Phương thức sendTextQuery() gửi truy vấn dạng 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() để khởi động 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 hãy nhấp vào nút "Khởi động lại trò chơi" nút, sendTextQuery() sẽ gọi 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 là được kích hoạt và BLOCKED nếu chưa đượ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 cam kết:

//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 một HtmlResponse vào ứ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 bên dưới:

//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 thêm một thẻ <mark> với một tên riêng biệt trong phản hồi SSML của bạn cho người dùng. Trong các phần trích dẫn sau từ Mẫu Người tuyết, OnTtsMark() đồng bộ hoá ảnh động của ứng dụng web với TTS tương ứng đầu ra. Khi Hành động nói với người dùng Rất tiếc, bạn đã thua, ứng dụng web sẽ hiển thị thông báo từ đúng và hiển thị chữ cái cho người dùng.

Ý định Game Over Reveal Word bao gồm một dấu tuỳ chỉnh để phản hồi của người dùng khi họ thua cuộc:

//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 dấu đó rồi thực thi hàm revealCorrectWord(). Hàm này 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ó định vị vị trí
  • Không sử dụng máy ảnh
  • Không có cửa sổ bật lên
  • Không vượt quá 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 cho video
  • Bạn chỉ có thể sử dụng một phần tử nội dung nghe nhìn tại một thời điểm
  • 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 hoặc video
  • Không áp dụng được 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 iframe và nguồn gốc được đặt thành rỗng, 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 bạn. Điều này cho phép thành phần của bạn chấp nhận các yêu cầu từ các nguồn gốc rỗng.