自定义 NVL 对话框
自定义 NVL 模式对白,可完全替换 NvlContainer,或用 renderDialogItem 调整 DefaultNvlContainer
选择自定义范围
NVL(Novel)模式以可滚动列表形式展示多条对话,适用于小说式叙事。通过 game.configure 的 nvlDialog 配置项,可替换默认的 NvlContainer 组件,实现完全自定义的 NVL 对话样式
有两种做法:使用 NvlContainer 替换整个容器,或保留 DefaultNvlContainer,只修改 renderDialogItem
1. 完全自定义 NVL 容器
使用 NvlContainer 作为外层,接收 dialogs 数组,自行渲染每条对话。INvlContainerProps 包含 dialogs 和可选的 renderDialogItem
import {
NvlContainer,
Nametag,
Texts,
type INvlContainerProps,
} from "narraleaf-react";
function CustomNvlContainer({ dialogs = [] }: INvlContainerProps) {
return (
<NvlContainer className="bg-black/80 text-white p-16">
{/* NvlContainer:处理可见性、过渡动画与宽高比缩放 */}
{dialogs.map((d) => (
<div key={d.entry.id} className="space-y-2 mb-4">
{/* d.entry:包含 character、sentence 等字段的 NvlDialogEntry */}
{d.entry.character && (
<Nametag entry={d.entry} className="text-amber-400 font-bold" />
)}
<Texts
entry={d.entry}
gameState={d.gameState}
words={d.words}
useTypeEffect={d.useTypeEffect}
isActive={d.isActive}
/>
</div>
))}
</NvlContainer>
);
}
2. 使用 renderDialogItem 定制单条对话
若只需调整每条对话的展示(如边框、透明度),可继续使用 DefaultNvlContainer,并传入 renderDialogItem 自定义布局:
import {
DefaultNvlContainer,
useGame,
type INvlContainerProps,
} from "narraleaf-react";
function CustomNvlWithRenderer({ dialogs, renderDialogItem }: INvlContainerProps) {
return (
<DefaultNvlContainer
dialogs={dialogs}
renderDialogItem={({ entry, index, isActive, nametag, texts }) => (
// nametag、texts:由 DefaultNvlContainer 预先渲染
<div className={`mb-4 ${isActive ? "opacity-100" : "opacity-60"}`}>
{nametag}
<div className="border-l-4 border-blue-500 pl-2">{texts}</div>
</div>
)}
/>
);
}3. renderDialogItem 参数说明
renderDialogItem 接收 NvlDialogItemRenderProps:
| 参数 | 类型 | 说明 |
|---|---|---|
entry | NvlDialogEntry | 对话条目(角色、句子等) |
index | number | 在列表中的索引 |
isActive | boolean | 是否为当前活动(打字中)的对话 |
nametag | React.ReactNode | 预渲染的角色名(无角色时为 null) |
texts | React.ReactNode | 预渲染的文本内容 |
4. 注册到游戏
import { Game, GameProviders, Player } from "narraleaf-react";
const game = new Game({ nvlDialog: CustomNvlContainer });
function App() {
return (
<GameProviders game={game}>
<Player story={story} onReady={({ liveGame }) => liveGame.newGame()} />
</GameProviders>
);
}如果只修改单条对话布局,把配置改为 CustomNvlWithRenderer
参考
- NvlContainer - NVL 容器 API
- game.configure - 游戏配置