pixi-vn-ui

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Pixi'VN User Interface (UI)

Pixi'VN 用户界面(UI)

Pixi’VN does not ship its own UI components (buttons, menus, forms, HUD). Instead of reinventing what already exists in the JavaScript ecosystem, it lets a project use any external framework (React, Vue, ...) — or plain PixiJS — to build the UI, and just provides the plumbing to mount that UI on top of the canvas and keep it in sync with game data. Official docs: pixi-vn.com/start/interface.
Because the UI is built with standard, widely-used frameworks rather than a proprietary system, AI coding assistants already know these tools well — this is a deliberate design choice, not just a missing feature.
Pixi'VN 并不自带 UI 组件(按钮、菜单、表单、HUD)。与其重复实现 JavaScript 生态中已经存在的能力,它允许项目使用任何外部框架(React、Vue、……)或纯 PixiJS 来构建 UI,并仅提供必要的衔接机制,将 UI 挂载到 canvas 上,同时使其与游戏数据保持同步。官方文档: pixi-vn.com/start/interface。
由于 UI 是使用标准且广泛使用的框架构建的,而非专有系统,因此 AI 编码助手通常已经非常熟悉这些工具。这是一种有意为之的设计选择,而不只是功能缺失。

When to use this skill

何时使用此 skill

Load this skill whenever a task involves:
  • Building a menu, HUD, dialogue box, settings screen, or save/load screen for a Pixi'VN game.
  • Mounting an HTML UI layer (React/Vue root) or a PixiJS UI layer on top of the canvas.
  • Navigating/switching between UI screens (routing).
  • Reading or writing game storage/settings from UI components, or keeping the UI in sync with changes made elsewhere (a label, a step, loading a save).
  • Theming/styling a template's generated UI (colors, radius, fonts).
For the rendering primitives the UI sits on top of (images, sprites, text, transitions), see
pixi-vn-canvas
. For building UI screens purely out of PixiJS components (no HTML framework), see
pixijs.md
in this same skill folder.
当任务涉及以下内容时,应加载此 skill:
  • 为 Pixi'VN 游戏构建菜单、HUD、对话框、设置界面或存档/读档界面。
  • 在 canvas 上挂载 HTML UI 层(React/Vue 根节点)或 PixiJS UI 层。
  • 在 UI 界面之间导航或切换(路由)。
  • 从 UI 组件读取或写入 game storage/settings,或让 UI 与其他位置的更改保持同步(label、step、加载存档)。
  • 对模板生成的 UI 进行主题化或样式设计(颜色、圆角、字体)。
若要了解 UI 所依托的渲染基础组件(图像、精灵、文本、转场),请参阅
pixi-vn-canvas
。若要完全使用 PixiJS 组件(不使用 HTML 框架)构建 UI 界面,请参阅同一 skill 文件夹中的
pixijs.md
。

UI vs canvas

UI 与 canvas

The UI and the canvas are two distinct, independent systems:
  • The canvas is save-able; the UI is not. All canvas element state (by alias) is included in a save and restored when loading one — see
    pixi-vn-storage
    /
    pixi-vn-saves
    . The UI's current state is never included; you must persist whatever UI state matters yourself, into game storage or browser storage (see "Connecting UI to game data" below).
  • The canvas is stepped; the UI is navigated. In the canvas you add/replace components during each narration step. The UI instead is built as several distinct "screens", and you move between them with a router (see "Navigating between UI screens" below) — you don't swap UI content per step the way you swap canvas elements.
  • The canvas is Pixi'VN-only; the UI is anything. The canvas only accepts Pixi'VN's own save-able component classes (
    Container
    ,
    Sprite
    ,
    ImageSprite
    ,
    Text
    , ...). The UI layer can hold any HTML/PixiJS component or any UI component library, so it's where the actual interface complexity (forms, animations, component libraries) belongs.
UI 和 canvas 是两个彼此独立的不同系统:
  • canvas 可以保存;UI 不可以。 所有 canvas 元素状态(按 alias 区分)都会包含在存档中,并在加载存档时恢复——参见
    pixi-vn-storage
    /
    pixi-vn-saves
    。UI 的当前状态绝不会被包含;你必须自行将所有需要保留的 UI 状态持久化到 game storage 或浏览器存储中(参见下文“将 UI 连接到游戏数据”)。
  • canvas 按 step 推进;UI 通过导航切换。 在 canvas 中,你会在每个叙述 step 添加或替换组件。UI 则构建为若干彼此独立的“界面”,并通过 router 在它们之间移动(参见下文“在 UI 界面之间导航”);你不会像替换 canvas 元素那样按 step 替换 UI 内容。
  • canvas 仅限 Pixi'VN;UI 不受限制。 canvas 只接受 Pixi'VN 自有的可保存组件类(
    Container
    、
    Sprite
    、
    ImageSprite
    、
    Text
    、……)。UI 层可以容纳任意 HTML/PixiJS 组件或任意 UI 组件库,因此表单、动画和组件库等真正的界面复杂度应放在这里。

HTML UI layers

HTML UI 层

An HTML UI Layer is a
<div>
added above the PixiJS canvas, sized and positioned to match it — this is how a React/Vue (or any DOM-based) UI gets mounted on top of the game.
ts
const root = document.getElementById("root");
if (!root) {
  throw new Error("root element not found");
}
const htmlLayer = canvas.htmlLayers.add("ui", root, {
  position: "absolute",
  pointerEvents: "none",
  userSelect: "none",
});
// createRoot(htmlLayer).render(<App />)
html
<!doctype html>
<html lang="en">
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>
  • canvas.htmlLayers.add(id, element, style?)
    creates the layer and returns the
    HTMLDivElement
    to render into.
    style
    is
    Partial<Pick<CSSStyleDeclaration, "position" | "pointerEvents" | "userSelect">>
    , defaulting to
    { position: "absolute", pointerEvents: "none", userSelect: "none" }
    .
  • canvas.htmlLayers.get(id)
    returns the layer's
    HTMLElement | undefined
    .
  • canvas.htmlLayers.remove(id)
    removes it.
Enabling interaction: every HTML UI layer defaults to
pointer-events: none
, so by default none of its elements intercept mouse/touch — the PixiJS canvas gets all events. This matters when you want an image/video on the canvas to receive clicks/taps unobstructed by an overlay. Set
pointer-events: auto
explicitly, and only, on the components that must be interactive:
tsx
export default function NextButton() {
  return <button style={{ pointerEvents: "auto" }}>Next</button>;
}
css
@layer components {
  [data-slot="button"],
  [data-slot="card"],
  [data-slot="toggle"] {
    pointer-events: auto;
  }
}
HTML UI 层是添加到 PixiJS canvas 上方的一个
<div>
,其尺寸和位置与 canvas 一致——React/Vue(或任何基于 DOM 的)UI 正是通过这种方式挂载到游戏上方的。
ts
const root = document.getElementById("root");
if (!root) {
  throw new Error("root element not found");
}
const htmlLayer = canvas.htmlLayers.add("ui", root, {
  position: "absolute",
  pointerEvents: "none",
  userSelect: "none",
});
// createRoot(htmlLayer).render(<App />)
html
<!doctype html>
<html lang="en">
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>
  • canvas.htmlLayers.add(id, element, style?)
    创建图层,并返回用于渲染内容的
    HTMLDivElement
    。
    style
    的类型为
    Partial<Pick<CSSStyleDeclaration, "position" | "pointerEvents" | "userSelect">>
    ,默认值为
    { position: "absolute", pointerEvents: "none", userSelect: "none" }
    。
  • canvas.htmlLayers.get(id)
    返回该图层的
    HTMLElement | undefined
    。
  • canvas.htmlLayers.remove(id)
    移除该图层。
启用交互:每个 HTML UI 层默认使用
pointer-events: none
,因此默认情况下,其中任何元素都不会拦截鼠标或触摸事件——所有事件都会交给 PixiJS canvas。当希望 canvas 上的图像或视频在不受覆盖层阻挡的情况下接收点击或触摸时,这一点尤其重要。请仅在必须交互的组件上显式设置
pointer-events: auto
:
tsx
export default function NextButton() {
  return <button style={{ pointerEvents: "auto" }}>Next</button>;
}
css
@layer components {
  [data-slot="button"],
  [data-slot="card"],
  [data-slot="toggle"] {
    pointer-events: auto;
  }
}

PixiJS UI layers

PixiJS UI 层

You can also build a UI screen directly out of PixiJS components (no HTML framework at all), or mix PixiJS components into an HTML-based UI. This uses a PixiJS UI Layer — a plain PixiJS
Container
attached directly to the PixiJS stage, outside the save-able
canvas.gameLayer
— via
canvas.layers.add
/
get
/
remove
. See
pixijs.md
in this skill folder for the full API, the differences from
gameLayer
, combining PixiJS and HTML layers, and recommended component libraries (PixiUI, PixiLayout).
你也可以完全使用 PixiJS 组件直接构建 UI 界面(无需任何 HTML 框架),或者将 PixiJS 组件混入基于 HTML 的 UI。这会使用 PixiJS UI 层——一个通过
canvas.layers.add
/
get
/
remove
直接附加到 PixiJS stage、且位于可保存的
canvas.gameLayer
之外的普通 PixiJS
Container
。有关完整 API、与
gameLayer
的区别、组合 PixiJS 层和 HTML 层的方法,以及推荐的组件库(PixiUI、PixiLayout),请参阅同一 skill 文件夹中的
pixijs.md
。

Real-world layer conventions (official React template)

实际项目中的图层约定(官方 React 模板)

The API above is library-level; here's one concrete way it's used in practice, from the official "TS narration + React" template (what
npm create pixi-vn@latest
scaffolds) at
src/main.tsx
/
src/constants.ts
. This is the template's convention, not a library requirement.
  • Named constants for layer ids, not string literals:
    CANVAS_UI_LAYER_NAME
    ,
    HTML_UI_LAYER_NAME
    ,
    HTML_CANVAS_LAYER_NAME
    . A separate
    CANVAS_MINIGAME_LAYER_NAME
    constant reserves a layer for future minigame content.
  • A dedicated PixiJS UI layer, added once at startup and kept apart from game-content elements (which live in
    canvas.gameLayer
    via
    canvas.add
    ):
    canvas.layers.add(CANVAS_UI_LAYER_NAME, new Container())
    .
  • canvas.htmlLayers.add
    to mount a UI framework's root as an actual canvas layer
    — not merely an absolutely-positioned
    <div>
    floating outside the canvas system:
    ts
    const htmlLayout = canvas.htmlLayers.add(HTML_UI_LAYER_NAME, root);
    createRoot(htmlLayout).render(<App />);
    Done inside
    Game.init(...).then(...)
    , after canvas setup, before rendering the app.
  • canvas.extractImage()
    for save-file thumbnails
    — captures a screenshot of the current canvas to embed in a save entry:
    const image = await canvas.extractImage();
    . (This is a
    canvas
    /save concern, not UI state — see
    pixi-vn-canvas
    /
    pixi-vn-saves
    .)
上述 API 属于库级接口;下面是一种具体用法,示例来自官方“TS narration + React”模板(
npm create pixi-vn@latest
脚手架所生成的内容),位于
src/main.tsx
/
src/constants.ts
。这是模板的约定,而不是库的强制要求。
  • 为图层 id 使用命名常量,而不是字符串字面量:
    CANVAS_UI_LAYER_NAME
    、
    HTML_UI_LAYER_NAME
    、
    HTML_CANVAS_LAYER_NAME
    。另一个独立的
    CANVAS_MINIGAME_LAYER_NAME
    常量为未来小游戏内容预留了图层。
  • 专用 PixiJS UI 层:在启动时添加一次,并与游戏内容元素分开;后者通过
    canvas.add
    存放在
    canvas.gameLayer
    中:
    canvas.layers.add(CANVAS_UI_LAYER_NAME, new Container())
    。
  • 使用
    canvas.htmlLayers.add
    将 UI 框架的根节点作为真正的 canvas 图层挂载
    ,而不是仅仅放置一个漂浮在 canvas 系统之外的绝对定位
    <div>
    :
    ts
    const htmlLayout = canvas.htmlLayers.add(HTML_UI_LAYER_NAME, root);
    createRoot(htmlLayout).render(<App />);
    这段代码位于
    Game.init(...).then(...)
    内部,在 canvas 设置完成之后、渲染 app 之前执行。
  • 使用
    canvas.extractImage()
    生成存档缩略图
    :截取当前 canvas 的屏幕截图并嵌入存档条目:
    const image = await canvas.extractImage();
    。(这是 canvas/存档相关问题,而不是 UI 状态问题——参见
    pixi-vn-canvas
    /
    pixi-vn-saves
    。)

Navigating between UI screens

在 UI 界面之间导航

Docs: pixi-vn.com/start/interface-navigate. To move between different UI screens, use a routing system that defines routes/paths for each screen and handles navigation between them — e.g. TanStack Router, which official templates use, with file-based route generation (
createFileRoute
, e.g. a file
about.tsx
under
src/routes
becomes the
/about
route).
Wiring
navigate
into narration steps
: extend
StepLabelProps
(typically in
pixi-vn.d.ts
, already done in every official template) so every step/
Game.onEnd
/
Game.addOnError
receives a
navigate
function:
ts
declare module "@drincs/pixi-vn" {
  interface StepLabelProps {
    navigate: (route: string) => void;
  }
}
ts
export const startLabel = newLabel("start", [
  ({ navigate }) => {
    navigate("/new-route");
  },
]);
In ink templates, a custom hashtag command navigates instead:
# navigate /new-route
.
Blocking the browser's back/forward buttons: those buttons let the player navigate between routes, not narrative steps, which can leave the game in an inconsistent state. The recommended approach is to intercept
popstate
and call
history.forward()
to cancel it, pushing a new history state on every route change so a second back-press in quick succession is still allowed through — see the
useConfirmBackNavigation
hook pattern in the official docs for the full implementation.
文档:pixi-vn.com/start/interface-navigate。要在不同 UI 界面之间移动,请使用路由系统,为每个界面定义 route/path,并处理它们之间的导航——例如官方模板采用的 TanStack Router,并使用基于文件的路由生成方式(
createFileRoute
;例如
src/routes
下的
about.tsx
文件会生成
/about
路由)。
将
navigate
接入叙述 step
:扩展
StepLabelProps
(通常在
pixi-vn.d.ts
中扩展;每个官方模板都已这样做),使每个 step/
Game.onEnd
/
Game.addOnError
都能接收到一个
navigate
function:
ts
declare module "@drincs/pixi-vn" {
  interface StepLabelProps {
    navigate: (route: string) => void;
  }
}
ts
export const startLabel = newLabel("start", [
  ({ navigate }) => {
    navigate("/new-route");
  },
]);
在 ink 模板中,则改用自定义 hashtag 命令进行导航:
# navigate /new-route
。
阻止浏览器的后退/前进按钮:这些按钮允许玩家在 route 之间导航,而不是在叙述 step 之间导航,因此可能使游戏处于不一致状态。推荐做法是拦截
popstate
并调用
history.forward()
来取消该操作,同时在每次 route change 时 push 新的 history state,使快速连续第二次按下后退键时仍可通过——完整实现请参阅官方文档中的
useConfirmBackNavigation
hook 模式。

Styling & theming

样式与主题

Docs: pixi-vn.com/start/interface-font. Official templates build the UI with shadcn/ui on Tailwind CSS — the component source is copied into
src/components/ui/
, not installed as an opaque package. The entire theme (colors, roundness, fonts) lives in one file,
src/styles.css
.
Rather than hand-editing
styles.css
, generate a theme with a visual tool and apply it:
  • shadcn/ui theme builder (official) — pick colors, mode, and radius with a live component preview, then copy a generated command:
    npm
    npx shadcn@latest add <generated-command>
  • tweakcn (community) — same colors/radius, plus live font/shadow editing and ready-made presets; exports plain CSS variables you paste into
    styles.css
    instead.
Either way, once the theme is applied, run:
npm
npm run ui:reinit
This force-reinstalls every shadcn component already in the project from the shadcn registry using the updated
styles.css
/
components.json
, so every component stays consistent with the new theme instead of keeping whatever variables it was originally built with.
文档:pixi-vn.com/start/interface-font。官方模板使用基于 Tailwind CSS 的 shadcn/ui 构建 UI——组件源码会被复制到
src/components/ui/
,而不是作为封装组件的 package 安装。整个主题(颜色、圆角、字体)都集中在一个文件
src/styles.css
中。
与其手动编辑
styles.css
,不如使用可视化工具生成主题并应用:
  • shadcn/ui theme builder(官方)——选择颜色、模式和圆角并实时预览组件,然后复制生成的命令:
    npm
    npx shadcn@latest add <generated-command>
  • tweakcn(社区工具)——提供相同的颜色和圆角设置,并支持实时编辑字体和阴影以及使用现成预设;它会导出可直接粘贴到
    styles.css
    中的普通 CSS 变量。
无论采用哪种方式,应用主题后都应运行:
npm
npm run ui:reinit
这会使用更新后的
styles.css
/
components.json
,从 shadcn registry 强制重新安装项目中已有的每个 shadcn 组件,使所有组件与新主题保持一致,而不是继续使用它们最初构建时所对应的变量。

Connecting UI to game data

将 UI 连接到游戏数据

Docs: pixi-vn.com/start/interface-connect-storage. Variables shown or edited in the UI fall into three categories, each with its own recommended pattern (official templates use these throughout
src/lib/stores/
and
src/lib/query/
):
Settings variables (text speed, font size, auto-forward delay, ...) are not part of game storage — they must persist across every playthrough, even before a save exists — so they live in
localStorage
, mirrored into a TanStack Store so components re-render on change:
ts
import { Store } from "@tanstack/store";

export namespace AutoSettings {
  export const store = new Store({
    enabled: Boolean(localStorage.getItem("auto_forward_enabled") ?? false),
    time: Number(localStorage.getItem("auto_forward_second") ?? 1),
  });

  export function setEnabled(value: boolean) {
    localStorage.setItem("auto_forward_enabled", value.toString());
    store.setState((state) => ({ ...state, enabled: value }));
  }
}
Read-only game variables (a stat, a flag, dialogue text) — read them straight from game storage inside a TanStack Query
queryFn
:
ts
import { useQuery } from "@tanstack/react-query";
import { storage } from "@drincs/pixi-vn";

export function useQueryAffection() {
  return useQuery({
    queryKey: ["affection_use_query_key"],
    queryFn: async () => storage.get<number>("affection") ?? 0,
  });
}
Game storage only changes during a step/go-back, a label call/jump, or loading a save — Pixi'VN has no way of knowing a query depends on that data, so invalidate broadly at those call sites rather than tracking every key:
ts
narration.continue({}).then(() => {
  queryClient.invalidateQueries();
});
Read/write game variables (a selected option, a toggle tied to a quest flag) — the same Store pattern as settings, but backed by game storage instead of
localStorage
, so the value survives saves and
go back
:
ts
import { storage } from "@drincs/pixi-vn";
import { Store } from "@tanstack/store";

export namespace Memo {
  export const store = new Store<{ selectedQuestId: string | undefined }>({
    selectedQuestId: storage.get<string>("selectedQuestId"),
  });

  export function setSelectedQuestId(id: string | undefined) {
    storage.set("selectedQuestId", id);
    store.setState((state) => ({ ...state, selectedQuestId: id }));
  }
}
Because the setter updates the Store directly, the UI stays in sync automatically — but only for changes made through this same setter.
Keeping the UI in sync with storage changes made elsewhere: if a label/step/anything else changes the same game storage variable directly, nothing tells that Store — or a
useQuery
reading that key — to refresh. Use
storage.setStorageHandler
to catch every game storage write in one place:
ts
import { storage } from "@drincs/pixi-vn";

storage.setStorageHandler({
  onSetVariable: (key, value) => queryClient.invalidateQueries(),
  onRemoveVariable: (key) => queryClient.invalidateQueries(),
  onClearOldTempVariable: (key) => queryClient.invalidateQueries(),
});
文档: pixi-vn.com/start/interface-connect-storage。 UI 中显示或编辑的变量分为三类,每类都有各自推荐的模式(官方模板在
src/lib/stores/
和
src/lib/query/
中 throughout 使用这些模式):
设置变量(文字速度、字号、自动前进延迟、……)不属于 game storage——即使尚未创建存档,它们也必须在每次游玩后保留——因此应存放在
localStorage
中,并同步到 TanStack Store,让组件在变量变化时重新渲染:
ts
import { Store } from "@tanstack/store";

export namespace AutoSettings {
  export const store = new Store({
    enabled: Boolean(localStorage.getItem("auto_forward_enabled") ?? false),
    time: Number(localStorage.getItem("auto_forward_second") ?? 1),
  });

  export function setEnabled(value: boolean) {
    localStorage.setItem("auto_forward_enabled", value.toString());
    store.setState((state) => ({ ...state, enabled: value }));
  }
}
只读游戏变量(属性值、flag、对话文本)——在 TanStack Query 的
queryFn
中直接从 game storage 读取:
ts
import { useQuery } from "@tanstack/react-query";
import { storage } from "@drincs/pixi-vn";

export function useQueryAffection() {
  return useQuery({
    queryKey: ["affection_use_query_key"],
    queryFn: async () => storage.get<number>("affection") ?? 0,
  });
}
game storage 只会在 step/go-back、label 调用/跳转或加载存档期间发生变化——Pixi'VN 无法知道某个 query 是否依赖这些数据,因此应在这些调用位置大范围执行 invalidate,而不是跟踪每一个 key:
ts
narration.continue({}).then(() => {
  queryClient.invalidateQueries();
});
可读写游戏变量(选中的选项、与任务 flag 绑定的开关)——与设置变量使用相同的 Store 模式,但由 game storage 而非
localStorage
支撑,因此其数值在存档/读档以及
go back
后仍然保留:
ts
import { storage } from "@drincs/pixi-vn";
import { Store } from "@tanstack/store";

export namespace Memo {
  export const store = new Store<{ selectedQuestId: string | undefined }>({
    selectedQuestId: storage.get<string>("selectedQuestId"),
  });

  export function setSelectedQuestId(id: string | undefined) {
    storage.set("selectedQuestId", id);
    store.setState((state) => ({ ...state, selectedQuestId: id }));
  }
}
由于 setter 会直接更新 Store,UI 会自动保持同步——但这只适用于通过同一个 setter 进行的更改。
让 UI 与其他地方发生的 storage 更改保持同步:如果 label/step 或其他代码直接更改了同一个 game storage 变量,系统不会通知对应 Store——也不会通知读取该 key 的
useQuery
——进行刷新。使用
storage.setStorageHandler
集中捕获每一次 game storage 写入:
ts
import { storage } from "@drincs/pixi-vn";

storage.setStorageHandler({
  onSetVariable: (key, value) => queryClient.invalidateQueries(),
  onRemoveVariable: (key) => queryClient.invalidateQueries(),
  onClearOldTempVariable: (key) => queryClient.invalidateQueries(),
});

Gotchas

常见注意事项

  • setStorageHandler
    does not stack — it replaces.
    It holds a single handler internally; every call overwrites the previous one silently. Set it once, in one place close to app start-up (e.g. the root provider), with a single handler that does everything the UI needs (invalidate queries, update stores, etc.) rather than sprinkling several targeted calls across files.
  • HTML UI layers default to
    pointer-events: none
    .
    Forgetting to set
    pointer-events: auto
    on an interactive component is the most common reason a button/input silently doesn't respond.
  • UI state is never saved automatically. If a UI-only value (a selected menu tab, a toggle not tied to game storage) needs to survive a reload, you must persist it yourself — game storage if it should survive save/load and
    go back
    ,
    localStorage
    if it should survive across playthroughs.
  • The browser back/forward buttons can desync the UI route from the narration state — see "Navigating between UI screens" above; most templates block them outright.
  • CANVAS_APP_GAME_LAYER_ALIAS
    (
    "__game_layer__"
    ) is reserved
    —
    canvas.layers.add
    (like
    canvas.add
    /
    remove
    ) refuses that alias for a PixiJS UI layer.
  • setStorageHandler
    不会叠加——它会进行替换。
    它内部只保存一个 handler;每次调用都会悄无声息地覆盖上一个 handler。应在靠近 app 启动位置的单一位置(例如根 provider)设置它一次,使用一个能够完成 UI 所有需求(使 query 失效、更新 store 等)的 handler,而不是在多个文件中分散调用针对特定场景的处理函数。
  • HTML UI 层默认使用
    pointer-events: none
    。
    如果忘记在可交互组件上设置
    pointer-events: auto
    ,按钮或输入框无响应是最常见的原因。
  • UI 状态永远不会自动保存。 如果某个仅供 UI 使用的值(选中的菜单标签、与 game storage 无关的开关)需要在重新加载后保留,就必须自行持久化:如果需要跨存档/读档和
    go back
    保留,请使用 game storage;如果需要跨多次游玩保留,请使用
    localStorage
    。
  • 浏览器的后退/前进按钮可能使 UI 路由与叙述状态不同步——参见上文“在 UI 界面之间导航”;大多数模板会直接阻止这些操作。
  • CANVAS_APP_GAME_LAYER_ALIAS
    (
    "__game_layer__"
    )是保留 alias
    ——
    canvas.layers.add
    (与
    canvas.add
    /
    remove
    一样)拒绝将该 alias 用于 PixiJS UI 层。

Related skills

相关 skill

  • pixi-vn-canvas: the rendering primitives (images, sprites, text, transitions) the UI sits on top of, and the
    gameLayer
    /alias system the UI deliberately does not use.
  • pixi-vn-getting-started:
    Game.init()
    ,
    StepLabelProps
    augmentation, and how the official template wires layers/routing/i18n together at startup.
  • pixi-vn-storage: reading/writing the game storage variables the UI reads and writes.
  • pixi-vn-saves: what does and does not get included when exporting/restoring game state.
  • pixi-vn-narration: labels/steps — what triggers storage changes the UI needs to react to.
  • pixi-vn-canvas:UI 所依托的渲染基础组件(图像、精灵、文本、转场),以及 UI 有意不使用的
    gameLayer
    /alias 系统。
  • pixi-vn-getting-started:
    Game.init()
    、
    StepLabelProps
    扩展,以及官方模板如何在启动时衔接图层/路由/i18n。
  • pixi-vn-storage:读取和写入 UI 所读写的 game storage 变量。
  • pixi-vn-saves:导出和恢复游戏状态时,哪些内容会被包含、哪些不会。
  • pixi-vn-narration:label/step——哪些操作会触发 UI 需要响应的 storage 更改。