網頁應用程式是指使用互動式畫布的動作的使用者介面。別擔心!您可以使用
現有的網頁技術 (HTML、CSS 和 JavaScript) 來設計及開發
即可快速導入 API互動式畫布大部分情況下,
但受到一些限制
保護使用者隱私與安全開始設計 UI 之前,請考慮
Design guidelines
所述設計原則
專區。
網頁應用程式的 HTML 和 JavaScript 會執行下列操作:
- 註冊互動式畫布事件回呼。
- 初始化互動式畫布 JavaScript 程式庫。
- 提供用於根據狀態更新網頁應用程式的自訂邏輯。
本頁將說明建構網頁應用程式的建議做法,以及如何啟用 網頁應用程式和執行要求之間的通訊,以及一般指南和 以及
推薦程式庫
雖然您可以使用任何方法建構 UI,但 Google 建議您使用下列做法 程式庫:
- Greensock:可建立複雜的動畫。
- Pixi.js:可在 WebGL 上繪製 2D 圖形。
- Three.js:可在 WebGL 上繪製 3D 圖形。
- HTML5 畫布繪圖:適用於簡單的繪圖。
- DOM 元素:適用於靜態內容。
架構
Google 強烈建議使用單頁應用程式架構。 這種做法可發揮最佳效能,並支援持續運作 對話式使用者體驗互動式畫布可與 包括 Vue、 Angular 和 React、 這有助於管理狀態
HTML 檔案
HTML 檔案會定義使用者介面的外觀。這個檔案也會載入 Canvas JavaScript 程式庫,啟用通訊功能 與對話式動作之間有何關聯
<!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>
在執行要求和網頁應用程式之間進行通訊
現在您已建構網頁應用程式,執行要求並載入到「互動」 畫布庫: 網頁應用程式檔案,您需要定義網頁應用程式和執行要求的互動方式。目的地: 修改內含網頁應用程式邏輯的檔案。
action.js
這個檔案內含要定義
回呼
並叫用方法
至 interactiveCanvas
。「回呼」功能可讓網頁應用程式回應
接收對話動作「來自」的資訊或要求
可讓使用者將資訊或要求「傳送至」對話動作。
將 interactiveCanvas.ready(callbacks);
加入 HTML 檔案,即可初始化並
註冊回呼:
//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
這個檔案會建立網頁應用程式的場景。在本例中,處理期間
針對 sendTextQuery()
傳回承諾的成功和失敗案例。
以下內容摘錄自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;
});
支援觸控互動
互動式畫布動作可以回應使用者的輕觸動作 使用者的聲帶根據 互動畫布設計指南, 您應該將動作設計為「優先語音回應」。儘管如此 螢幕支援觸控互動。
輔助觸控功能類似支援對話式回應;不過 用戶端 JavaScript 會以 ,並用該元件變更網頁應用程式中的元素。
這個範例中的這個範例使用 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;
});
...
在此情況下,spin
變數的值會透過
interactiveCanvas
API 做為 update
回呼。執行要求有邏輯
根據 spin
的值觸發意圖。
...
app.intent('pause', (conv) => {
conv.ask(`Ok, I paused spinning. What else?`);
conv.ask(new HtmlResponse({
data: {
spin: false,
},
}));
});
...
新增其他功能
現在您已經瞭解基本概念,現在可以強化及自訂動作了 搭配 Canvas 專用的 API本節說明如何實作這些 API 以及互動式畫布動作
sendTextQuery()
sendTextQuery()
方法會將文字查詢傳送至對話動作
透過程式輔助方式叫用意圖此範例使用 sendTextQuery()
來
當使用者點選按鈕時,重新啟動三角形轉動的遊戲。當使用者
按一下 [重新啟動遊戲]按鈕,sendTextQuery()
會呼叫 Restart game
並傳回承諾使用的值如果意圖是 SUCCESS
,
否則會觸發 BLOCKED
。下列程式碼片段會觸發意圖
並處理承諾的成功和失敗案例:
//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}`);
}
});
...
如果承諾的結果產生 SUCCESS
,Restart game
意圖就會傳送 HtmlResponse
。
為您的網頁應用程式:
//index.js
...
app.intent('restart game', (conv) => {
conv.ask(new HtmlResponse({
data: {
command: 'RESTART_GAME',
},
...
這個 HtmlResponse
會觸發 onUpdate()
回呼,後者會執行程式碼
在以下 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()
當您在以下項目中加入擁有不重複名稱的 <mark>
標記時,系統會呼叫 OnTtsMark()
回呼
您的 SSML 回應以下摘錄自雪人範例的摘錄中
OnTtsMark()
會將網頁應用程式的動畫與對應的 TTS 同步處理
輸出內容使用者「很抱歉,你遺失了」動作時,網頁應用程式會拼寫錯誤
正確的字詞並向使用者顯示字母。
意圖 Game Over Reveal Word
在回應
則會導致玩家流失:
//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());
});
...
下列程式碼片段會註冊 OnTtsMark()
回呼,並檢查名稱
,然後執行 revealCorrectWord()
函式,該函式會更新網頁應用程式:
//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();
}
},
...
限制
開發網頁應用程式時,請考量以下限制:
- 沒有 Cookie
- 沒有本機儲存空間
- 無地理位置
- 未使用攝影機
- 沒有彈出式視窗
- 將記憶體用量限制在 200 MB 以下
- 第三方標頭佔據畫面的上方部分
- 影片未套用任何樣式
- 一次只能使用一個媒體元素
- 沒有 HTTP 即時串流影片
- 沒有任何網路 SQL 資料庫
- 不支援
SpeechRecognition
介面 Web Speech API。 - 沒有錄音或錄影
- 無法使用深色模式設定
跨源資源共享
因為互動式畫布網頁應用程式是由 iframe 代管,且來源已設定 設為空值,您必須啟用跨源資源共享 (CORS) 網路伺服器和儲存空間資源這樣一來,您的素材資源就能接受 來自空值來源的要求。
- 如果您的媒體和圖片是由 Firebase 代管,請參閱「建立自訂 網域動態連結 設定 CORS
- 如果您的媒體和圖片位於 Cloud Storage 中,請參閱「設定跨來源」 資源共用 (CORS) 設定 CORS