猹引擎
页面交互代码
本页用于完整说明 ChaEngine 页面交互层的写法,包含页面通信、玩家数据、槽位交互三类能力。
页面通信流程
页面交互由四段组成:
- 页面就绪:等待
chaengine:ready。 - 上行请求:页面把点击行为发给服务端。
- 下行回推:服务端把处理结果发回页面。
- 视图刷新:页面按最新数据重绘。
最小可用骨架
html
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<title>ChaEngine 页面模板</title>
</head>
<body>
<button id="btnSync">同步状态</button>
<pre id="log"></pre>
<script>
const log = (msg) => {
document.getElementById('log').textContent += msg + '\n';
};
window.addEventListener('chaengine:ready', () => {
log('SDK ready');
// 接收服务端回推
ChaEngine.onServerData((packet) => {
log(`[S2C] ${packet.channel} => ${packet.data}`);
});
});
document.getElementById('btnSync').addEventListener('click', async () => {
await ChaEngine.sendToServer('ui.state.sync', {
action: 'sync_state',
pageId: 'activity.main'
});
log('[C2S] 请求同步已发送');
});
</script>
</body>
</html>常用 API 一览
| API | 用途 | 典型场景 |
|---|---|---|
ChaEngine.openUi(id) | 打开页面 | 首页跳转到商店页 |
ChaEngine.sendToServer(channel, data) | 发送上行数据 | 提交购买、提交任务 |
ChaEngine.onServerData(handler) | 接收下行数据 | 刷新列表、弹出结果提示 |
ChaEngine.getPlayerData() | 读取玩家数据 | HUD 显示血量、经验 |
ChaEngine.onPlayerData(handler) | 监听玩家数据变化 | 实时更新状态条 |
ChaEngine.getCachedPlayerData() | 读取最近缓存 | 页面初始快速渲染 |
ChaEngine.openUrl(url, title) | 打开外链 | 打开公告链接 |
ChaEngine.openHtml(html, title) | 打开内联页 | 打开临时提示页 |
页面通信模板
模板一:按钮动作上报
html
<button id="btnEnter">进入活动</button>
<script>
document.getElementById('btnEnter').addEventListener('click', async () => {
await ChaEngine.sendToServer('activity.action', {
action: 'enter_activity',
pageId: 'activity.main'
});
});
</script>模板二:表单提交
html
<input id="nameInput" placeholder="输入称号" />
<button id="btnSave">保存</button>
<script>
document.getElementById('btnSave').addEventListener('click', async () => {
const value = document.getElementById('nameInput').value;
await ChaEngine.sendToServer('profile.action', {
action: 'save_title',
value
});
});
</script>模板三:列表分页
html
<button id="btnPrev">上一页</button>
<button id="btnNext">下一页</button>
<script>
let currentPage = 1;
async function queryPage(page) {
await ChaEngine.sendToServer('shop.query', {
action: 'query_page',
page,
size: 12
});
}
document.getElementById('btnPrev').addEventListener('click', () => {
currentPage = Math.max(1, currentPage - 1);
queryPage(currentPage);
});
document.getElementById('btnNext').addEventListener('click', () => {
currentPage += 1;
queryPage(currentPage);
});
</script>玩家数据模板
模板一:拉取一次玩家数据
html
<script>
window.addEventListener('chaengine:ready', async () => {
const player = await ChaEngine.getPlayerData();
console.log('玩家名', player.name);
console.log('当前血量', player.health, '/', player.maxHealth);
});
</script>模板二:实时监听玩家数据
html
<script>
window.addEventListener('chaengine:ready', () => {
ChaEngine.onPlayerData((player) => {
const ratio = player.maxHealth > 0 ? player.health / player.maxHealth : 0;
document.body.style.setProperty('--hp-ratio', String(ratio));
});
});
</script>模板三:页面秒开先用缓存
html
<script>
const cached = ChaEngine.getCachedPlayerData();
if (cached) {
console.log('缓存血量', cached.health, '/', cached.maxHealth);
}
</script>HTML槽位交互模板
页面结构示例
html
<div class="slot" data-slot="hotbar_0">快捷栏1</div>
<div class="slot" data-slot="necklace_0">项链槽</div>槽位绑定与点击
html
<script>
window.addEventListener('chaengine:ready', async () => {
await ChaEngine.bindSlots([
{ id: 'hotbar_0', type: 'player', index: 0 },
{ id: 'necklace_0', type: 'custom', config: '项链槽位', slot: 0 }
]);
ChaEngine.onSlotData((packet) => {
if (packet.detail.type !== 'snapshot') return;
for (const slot of packet.detail.slots) {
const node = document.querySelector(`[data-slot="${slot.id}"]`);
if (!node) continue;
node.classList.toggle('slot-empty', !slot.item);
}
});
});
document.addEventListener('click', async (event) => {
const slot = event.target.closest('[data-slot]');
if (!slot) return;
await ChaEngine.clickSlot(slot.dataset.slot, {
button: event.button === 2 ? 'right' : 'left',
shift: event.shiftKey
});
});
</script>槽位同步与清理
html
<script>
async function syncSlotsNow() {
await ChaEngine.syncSlots();
}
async function clearCurrentBindings() {
await ChaEngine.clearSlotBindings();
}
</script>更多说明见:
通道命名
| 模块 | 通道名 |
|---|---|
| 页面动作上报 | ui.action |
| 页面状态同步 | ui.state |
| 页面提示消息 | ui.notice |
| 商店行为 | shop.action |
| 任务行为 | quest.action |
页面交互排错
- 页面是否通过 ChaEngine 打开。
- 页面是否收到
chaengine:ready。 - 上行通道名是否和服务端约定一致。
- 下行监听是否先注册再请求。
- 有槽位时是否先执行
bindSlots。
猹件开发组