Skip to content
On this page

猹引擎

页面交互代码

本页用于完整说明 ChaEngine 页面交互层的写法,包含页面通信、玩家数据、槽位交互三类能力。

页面通信流程

页面交互由四段组成:

  1. 页面就绪:等待 chaengine:ready
  2. 上行请求:页面把点击行为发给服务端。
  3. 下行回推:服务端把处理结果发回页面。
  4. 视图刷新:页面按最新数据重绘。

最小可用骨架

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

页面交互排错

  1. 页面是否通过 ChaEngine 打开。
  2. 页面是否收到 chaengine:ready
  3. 上行通道名是否和服务端约定一致。
  4. 下行监听是否先注册再请求。
  5. 有槽位时是否先执行 bindSlots