Если у вас Pro аккаунт и программирование для вас это не пустой звук, вы можете писать сценарии прямо на JavaScript. Это дает более широкие возможности и гибкость, вы не ограничены только теми блоками, которые есть в редакторе блоков, но взаимодействие с туром все равно идет только по API.
Использовать JavaScript можно только на Pro аккаунте.
API одинаковое для использования в сценариях и вставки своего кода для тура. Почитать о нем можно в разделе "API", а здесь мы приведет только общие рекомендации именно для сценариев.
Скрипт сценария не живет в глобальной области видимости, но мы даем все самое необходимое:
runtime - общая память (словарь) на весь тур или сцену.
runtime.tour // общая память на весь тур
runtime.scene // память текущей сцены
runtime.tour.score = runtime.tour.score || 0
runtime.tour.score += 1
ipano.toast('Очки: ' + runtime.tour.score)
trigger - что запустило сценарий.
utils.log('Запуск сценария', trigger)
if (trigger.type === 'start') {
ipano.toast('Сценарий запущен при старте сцены')
}
if (trigger.type === 'click') {
ipano.toast('Сценарий запущен кликом')
if (trigger.source === 'media') {
utils.log('Кликнули медиа-точку', {
pointPk: trigger.pointPk,
mediaPk: trigger.mediaPk
})
}
}
if (trigger.type === 'manual') {
ipano.toast('Сценарий запущен вручную')
}utils - функции, необходимые для работы
// utils.log: лог с префиксом сценария
utils.log('Сообщение', { sceneId })
// utils.sleep: пауза, всегда в миллисекундах
await utils.sleep(1000)
// utils.setTimeout: выполнить один раз через N мс
utils.setTimeout(function () {
ipano.toast('Прошла 1 секунда')
}, 1000)
// utils.setInterval: повторять каждые N мс
utils.setInterval(function () {
utils.log('tick')
}, 2000)
// Если внутри interval есть await, ставь защиту от наложения запусков
let busy = false
utils.setInterval(async function () {
if (busy) return
busy = true
try {
utils.log('Делаем долгую задачу')
await utils.sleep(1500)
} finally {
busy = false
}
}, 1000)
// utils.fetchJson: загрузить JSON
const data = await utils.fetchJson('/api/data.json')
// По умолчанию JSON кешируется. Чтобы всегда грузить свежий:
const freshData = await utils.fetchJson('/api/data.json', {
cache: false
})
// POST JSON
const result = await utils.fetchJson('/api/check', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ answer: 'A' }),
cache: false
})
// utils.jsonGetField: взять поле объекта
const title = utils.jsonGetField(data, 'title')
// utils.jsonGetIndex: взять элемент массива
const firstItem = utils.jsonGetIndex(data.items, 0)
// utils.jsonGetPath: взять значение по пути
const name = utils.jsonGetPath(data, 'items[0].name')
// utils.on: подписка на событие
utils.on('scenechange', function (payload) {
utils.log('Смена сцены', payload)
})
// utils.once: подписка один раз
utils.once('scenechange', function (payload) {
ipano.toast('Сцена сменилась один раз')
})
// utils.watchObjectVisibility: следить за видимостью объекта "Меня видно"
utils.watchObjectVisibility('interactive:42', function (payload) {
utils.log('Видимость:', payload.visible)
})
// utils.onObjectEnterView: объект попал в поле зрения
utils.onObjectEnterView('interactive:42', function (payload) {
ipano.toast('Объект в кадре')
})
// utils.onObjectLeaveView: объект ушел из поля зрения
utils.onObjectLeaveView('interactive:42', function (payload) {
ipano.toast('Объект не в кадре')
})