Веб-приложение — это пользовательский интерфейс для действия, использующего интерактивное полотно. Вы можете использовать существующие веб-технологии (HTML, CSS и JavaScript) для проектирования и разработки своего веб-приложения. По большей части Interactive Canvas способен отображать веб-контент так же, как браузер, но существует несколько ограничений для обеспечения конфиденциальности и безопасности пользователей. Прежде чем приступить к разработке пользовательского интерфейса, рассмотрите принципы проектирования, изложенные в разделе Design guidelines
.
HTML и JavaScript вашего веб-приложения выполняют следующие действия:
- Зарегистрируйте обратные вызовы событий Interactive Canvas.
- Инициализируйте библиотеку JavaScript Interactive Canvas.
- Предоставьте собственную логику для обновления вашего веб-приложения в зависимости от состояния.
На этой странице описаны рекомендуемые способы создания вашего веб-приложения, способы обеспечения связи между вашим веб-приложением и выполнением, а также общие рекомендации и ограничения.
Рекомендуемые библиотеки
Хотя вы можете использовать любой метод для создания пользовательского интерфейса, Google рекомендует использовать следующие библиотеки:
- Greensock : для создания сложных анимаций.
- Pixi.js : для рисования 2D-графики в WebGL.
- Three.js : для рисования 3D-графики в WebGL.
- Рисунок на холсте HTML5 : для простых рисунков.
- Элемент DOM : для статического контента.
Архитектура
Google настоятельно рекомендует использовать одностраничную архитектуру приложений. Такой подход обеспечивает оптимальную производительность и поддерживает непрерывное общение с пользователем. Interactive Canvas можно использовать в сочетании с интерфейсными фреймворками, такими как Vue , Angular и React , которые помогают управлять состоянием.
HTML-файл
HTML-файл определяет, как выглядит ваш пользовательский интерфейс. Этот файл также загружает библиотеку JavaScript Interactive Canvas, которая обеспечивает связь между вашим веб-приложением и диалоговым действием.
<!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>
Взаимодействие между выполнением и веб-приложением
Теперь, когда вы создали свое веб-приложение и выполнение и загрузили библиотеку Interactive Canvas в файл вашего веб-приложения, вам необходимо определить, как взаимодействуют ваше веб-приложение и выполнение. Для этого измените файлы, содержащие логику вашего веб-приложения.
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;
});
Поддержка сенсорного взаимодействия
Ваше интерактивное действие на холсте может реагировать как на прикосновения пользователя, так и на его голосовые команды. В соответствии с рекомендациями по проектированию Interactive Canvas вы должны разработать свое действие так, чтобы оно было приоритетным. При этом некоторые умные дисплеи поддерживают сенсорное взаимодействие.
Поддержка прикосновений аналогична поддержке разговорных ответов; однако вместо голосового ответа пользователя ваш клиентский 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
отправляется через API interactiveCanvas
в качестве обратного вызова update
. Выполнение имеет логику, которая запускает намерение на основе значения spin
.
...
app.intent('pause', (conv) => {
conv.ask(`Ok, I paused spinning. What else?`);
conv.ask(new HtmlResponse({
data: {
spin: false,
},
}));
});
...
Добавить больше функций
Теперь, когда вы изучили основы, вы можете улучшить и настроить свое действие с помощью API-интерфейсов, специфичных для Canvas. В этом разделе объясняется, как реализовать эти 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()
Обратный вызов OnTtsMark()
вызывается, когда вы включаете тег <mark>
с уникальным именем в свой SSML-ответ пользователю. В следующих фрагментах примера Snowman 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 МБ.
- Заголовок 3P занимает верхнюю часть экрана.
- К видео нельзя применять стили.
- Одновременно можно использовать только один медиа-элемент
- Нет HLS-видео
- Нет базы данных Web SQL
- Нет поддержки интерфейса
SpeechRecognition
API Web Speech . - Нет аудио и видео записи
- Настройка темного режима неприменима.
Совместное использование ресурсов между источниками
Поскольку веб-приложения Interactive Canvas размещаются в iframe, а для источника установлено значение null, необходимо включить совместное использование ресурсов между источниками (CORS) для ваших веб-серверов и ресурсов хранения. Это позволяет вашим активам принимать запросы от нулевых источников.
- Если ваши медиафайлы и изображения размещены в Firebase, см. раздел Создание динамических ссылок личного домена для настройки CORS.
- Если ваши медиафайлы и изображения находятся в облачном хранилище, см. раздел Настройка совместного использования ресурсов между источниками (CORS), чтобы настроить CORS.