☰
BongoCat 跨平台互动桌宠全解析:基于 Tauri 2 与 Live2D 的键盘、鼠标、手柄联动实现
2026/9/30 1:41:46 网站建设 项目流程
  • 桌面应用
  • 前端

【免费下载链接】BongoCat

🐱 跨平台互动桌宠 BongoCat,为桌面增添乐趣!

项目地址:https://gitcode.com/ayangweb/BongoCat
点击查看免费下载

BongoCat 是一款使用 Tauri 2 + Vue 3 + Live2D(Cubism)构建的开源跨平台互动桌宠,能够实时响应键盘、鼠标和手柄操作并驱动猫咪模型做出对应动作。本文以仓库 README.md 为主线,结合前端源码与 Rust 后端实现,完整讲解它的开发背景、核心交互链路、模型加载机制、窗口配置与跨平台打包方案,帮助你理解并复现这类桌宠应用的关键技术。

开发背景:从 Windows 独占到跨平台桌宠

BongoCat 的灵感来源于 Bongo-Cat-Mver 这一经典的猫咪互动桌宠。原版凭借独特的猫咪互动玩法深受用户喜爱,但仅支持 Windows 平台。为了在 macOS 上也能使用,作者决定开发适配 macOS 的版本,并进一步借助 Tauri 的跨平台能力,让同一套代码同时兼容 macOS、Windows 和 Linux(x11)。

这一背景直接决定了项目的几个关键设计取向:

  • 跨平台一致的行为体验:键盘、鼠标、手柄输入在三个平台上都能驱动模型;
  • 轻量的桌面壳:选择 Tauri 而非 Electron,前端资源由系统 WebView 承载,桌面端逻辑由 Rust 实现,应用体积与内存占用更小;
  • 完全开源与离线可用:代码公开透明,运行不依赖网络。

技术栈与仓库结构总览

从前端依赖清单(package.json)可以看到项目的完整技术栈:

领域技术选型用途
桌面框架Tauri 2(@tauri-apps/api^2.10.1、@tauri-apps/cli^2.10.1)窗口管理、系统能力桥接
前端框架Vue 3(^3.5.32)+ Pinia(^3.0.4)+ vue-router + vue-i18nUI、状态、路由与多语言
Live2D 渲染easy-live2d(^0.4.4)+pixi.js(^8.18.1)模型加载、渲染与动作播放
输入监听(Rust)rdev、gilrs全局键盘/鼠标、手柄事件捕获
UI 组件antdv-next偏好设置界面

仓库核心目录如下:

  • src/composables/useKeyPress.ts、src/composables/useGamepad.ts、src/composables/useModel.ts:前端输入与模型状态编排;
  • src/utils/live2d.ts:Live2D 模型的加载、缩放、动作与参数控制;
  • src-tauri/src/core/device.rs、src-tauri/src/core/gamepad.rs:Rust 侧全局输入监听;
  • src-tauri/tauri.conf.json:窗口、安全与打包配置。

核心交互链路:键盘、鼠标、手柄如何驱动猫咪

README 中"根据键盘、鼠标或手柄的操作,同步对应的动作"是 BongoCat 的核心功能。这条链路在架构上分为三层:

1. Rust 后端:全局输入捕获与事件广播

后端使用rdev捕获全局键盘/鼠标事件,见 src-tauri/src/core/device.rs:

let callback = move |event: Event| { let device_event = match event.event_type { EventType::ButtonPress(button) => DeviceEvent { kind: DeviceEventKind::MousePress, value: json!(format!("{:?}", button)) }, EventType::ButtonRelease(button)=> DeviceEvent { kind: DeviceEventKind::MouseRelease, value: json!(format!("{:?}", button)) }, EventType::MouseMove { x, y } => DeviceEvent { kind: DeviceEventKind::MouseMove, value: json!({ "x": x, "y": y }) }, EventType::KeyPress(key) => DeviceEvent { kind: DeviceEventKind::KeyboardPress, value: json!(format!("{:?}", key)) }, EventType::KeyRelease(key) => DeviceEvent { kind: DeviceEventKind::KeyboardRelease, value: json!(format!("{:?}", key)) }, _ => return, }; let _ = app_handle.emit("device-changed", device_event); };

关键点:

  • 通过start_device_listening命令启动监听(对应前端常量 src/constants/index.ts 中的START_DEVICE_LISTENING),使用AtomicBool保证监听只启动一次,避免重复注册;
  • 捕获到的事件统一通过 Tauri 的emit以device-changed事件名推送到前端,事件类型枚举为MousePress / MouseRelease / MouseMove / KeyboardPress / KeyboardRelease。

手柄部分则由 src-tauri/src/core/gamepad.rs 基于gilrs实现,以start_gamepad_listing/stop_gamepad_listing两个命令控制启停,并将ButtonChanged、AxisChanged事件以gamepad-changed事件名推送到前端。

2. 前端监听:事件到 Live2D 参数的映射

前端通过useTauriListen订阅这两个事件。以手柄为例,src/composables/useGamepad.ts 会把摇杆与按键事件映射为模型参数:

  • 左摇杆 X/Y →CatParamStickLX/CatParamStickLY;
  • 右摇杆 X/Y →CatParamStickRX/CatParamStickRY;
  • 左/右摇杆按下 →CatParamStickLeftDown/CatParamStickRightDown;
  • 摇杆"是否接触"状态 →CatParamStickShowLeftHand/CatParamStickShowRightHand;
  • 其余按键 → 按下时调用handlePress(name),松开时调用handleRelease(name)。

模型参数通过 src/utils/live2d.ts 的setParameterValue写入:

public setParameterValue(id: string, value: number | boolean) { return this.model?.setParameterValueById(id, Number(value)) }

3. 动作映射规则

键盘与鼠标的映射集中在 src/composables/useModel.ts:

  • 左右手按下:CatParamLeftHandDown/CatParamRightHandDown(handleKeyChange);
  • 鼠标左/右键:ParamMouseLeftDown/ParamMouseRightDown(handleMouseChange);
  • 鼠标移动:根据光标在显示器上的比例位置,计算ParamMouseX/Y、ParamAngleX/Y/Z、ParamEyeBallX/Y等参数,并通过getParameterValueRange读取模型参数范围做归一化映射(handleMouseMove)。

handlePress还会根据按键路径判断是否存在同手按键冲突,并自动释放上一键(findKey+handleRelease),保证猫咪左右手动作互不抢占。

Live2D 模型加载与渲染管线

模型的加载、渲染全部在前端完成,核心实现位于 src/utils/live2d.ts。

加载流程

public async load(path: string) { await this.initApp() this.destroy() const files = await readDir(path) const modelFile = files.find(file => file.name.endsWith('.model3.json')) if (!modelFile) throw new Error(i18n.global.t('utils.live2d.hints.notFound')) const modelPath = join(path, modelFile.name) const modelJSON = JSON5.parse(await readTextFile(modelPath)) const modelSetting = new CubismSetting({ modelJSON }) modelSetting.redirectPath(({ file }) => convertFileSrc(join(path, file))) this.model = new Live2DSprite({ modelSetting, ticker: Ticker.shared }) this.app?.stage.addChild(this.model) await this.model.ready // ...返回 width/height/motions/expressions }

几个值得注意的实现细节:

  • 渲染器:基于 Pixi.js 8 的Application,画布为live2dCanvas,配置backgroundAlpha: 0实现透明背景、autoDensity+devicePixelRatio适配高分屏;
  • 模型目录识别:通过查找目录下*.model3.json定位模型定义文件,并用JSON5解析(兼容带注释的模型配置);
  • 资源路径重定向:通过redirectPath把模型内引用的贴图、表情等资源重定向为convertFileSrc生成的本地协议地址,从而支持从任意自定义目录加载模型;
  • 等比缩放:resizeModel依据窗口与模型宽高比取min(scaleX, scaleY)居中放置模型,避免拉伸变形。

动作与表情

加载完成后会返回motions(按 group 分组)和expressions。startMotion以Priority.Normal播放动作,setExpression切换表情。值得注意的是,加载模型时会为每个动作/表情自动生成默认快捷键,见 src/composables/useModel.ts:按Command(macOS)/Control(其他平台)加上Shift/Alt的组合,依次分配数字键1-0与字母键QWERTYUIOPASDFGHJKLZXCVBNM。

全局快捷键与窗口行为

桌宠需要"藏起来也能唤起",因此项目使用了@tauri-apps/plugin-global-shortcut。封装的 src/composables/useKeyPress.ts 提供响应式快捷键绑定:

export function useKeyPress(shortcut: Ref<string | undefined, string>, callback: ShortcutHandler) { const oldShortcut = ref(shortcut.value) async function unbind() { if (!oldShortcut.value) return const registered = await isRegistered(oldShortcut.value) if (!registered) return return unregister(oldShortcut.value) } watch(shortcut, async (value) => { await unbind() if (!value) return await register(value, (event) => { if (event.state === 'Released') return callback(event) }) oldShortcut.value = value }, { immediate: true }) onUnmounted(unbind) }

它实现了三个细节:配置变更时自动解绑旧快捷键、忽略按键释放事件、组件卸载时自动清理,避免全局快捷键泄漏。

透明桌宠窗口:Tauri 配置解析

BongoCat 的桌宠窗口是"透明、无边框、永远置顶、不占任务栏"的,这一整套行为在 src-tauri/tauri.conf.json 中配置:

{ "label": "main", "title": "BongoCat", "url": "index.html/#/", "shadow": false, "alwaysOnTop": true, "transparent": true, "decorations": false, "acceptFirstMouse": true, "skipTaskbar": true, "maximizable": false }

参数含义:

参数作用
transparent: true窗口背景透明,配合 Canvas 的backgroundAlpha: 0呈现"只有猫咪"的视觉效果
decorations: false去掉系统标题栏与边框
alwaysOnTop: true窗口始终位于最上层,猫咪随时可见
skipTaskbar: true不在任务栏/程序坞显示图标
shadow: false关闭窗口阴影,避免透明窗口出现黑边
acceptFirstMouse: truemacOS 下点击无焦点窗口时同时响应事件

项目还定义了一个隐藏的preference窗口(visible: false、minWidth: 800、minHeight: 600)用于承载偏好设置页面。macOS 上额外启用了macOSPrivateApi: true以获得透明置顶窗口所需的私有 API 能力。

自定义模型:格式、导入与转换

README 明确支持"导入自定义模型,自由打造专属猫咪形象",这与仓库内置的模型资源结构一致。以 src-tauri/assets/models 为例,每个模型目录包含:

  • cat.model3.json:模型入口定义(Cubism 3 模型描述文件);
  • *.moc3:模型几何与骨骼数据;
  • *.cdi3.json:模型参数/部件/表情的索引定义;
  • *.1024/texture_*.png:贴图资源(1024×512 的标准贴图尺寸);
  • *.motion3.json与*.flac:动作文件及其配音;
  • live2d_expression*.exp3.json、exp_*.exp3.json:表情定义。

内置了standard、keyboard、gamepad三套模型,对应不同输入模式的演示资源(见 tauri.conf.json 的resources配置将assets/models打包进应用)。

对于从 Bongo-Cat-Mver 带来的旧模型,README 提供了在线模型转换工具(BongoCat 社区维护的转换服务),可将 Bongo-Cat-Mver 应用的模型转换为兼容 BongoCat 的格式后导入使用。同时社区仓库Awesome-BongoCat收录了大量可下载的猫咪模型,也欢迎提交自己的创作与大家分享。

下载、安装与跨平台打包

获取安装包

安装包通过两个渠道分发:夸克网盘与 GitHub Releases;不确定该下载哪个平台版本时,可参照 README 中附带的下载指南。macOS、Windows、Linux(x11) 三平台均有对应安装包。

打包目标

从 tauri.conf.json 的bundle.targets可以看到各平台打包产物:

"targets": ["nsis", "dmg", "app", "appimage", "deb", "rpm"]
  • Windows:NSIS 安装包;
  • macOS:dmg 磁盘映像与 app 目录;
  • Linux:AppImage、deb、rpm 三种格式。

应用还启用了@tauri-apps/plugin-updater(createUpdaterArtifacts: true),内置自动更新能力,更新端点配置在plugins.updater.endpoints中,支持按current_version、target、arch动态拼接更新地址。

本地开发

仓库使用 pnpm 管理依赖(preinstall强制only-allow pnpm),常用脚本见 package.json:

pnpm dev # 开发模式:先构建图标再启动 Vite(devUrl: http://localhost:1420) pnpm build # 依次执行 vite build、图标构建等 pnpm tauri # 调用 Tauri CLI pnpm lint # eslint --fix 自动修复 src

Rust 侧在 src-tauri/src/core/mod.rs 中聚合了device、gamepad、prevent_default、setup四个模块,setup模块按平台区分 macOS 与其它系统的初始化逻辑(见 src-tauri/src/core/setup/mod.rs)。

隐私与离线:数据边界承诺

README 明确列出两条重要承诺:

  • 完全开源,代码公开透明:桌面端 Rust 源码(src-tauri/)与前端源码(src/)全部开放,可审计;
  • 绝不收集任何用户数据 + 支持离线运行:输入监听仅用于驱动本地模型动画,事件在本地经 Tauri 事件总线流转后直接映射为 Live2D 参数,不涉及任何网络上报;模型、贴图、动作文件均打包在应用内(assets/models),离线即可运行。

从代码实现看,输入事件只被用于设置 Live2D 参数(setParameterValue),没有发现任何数据外发逻辑,与 README 的隐私承诺一致。

社区生态与参与贡献

BongoCat 围绕桌宠形成了一个小生态:官方维护的模型转换工具降低旧模型迁移成本,Awesome-BongoCat 模型仓库提供更多形象与投稿渠道,社区交流通过 QQ 群进行。想要参与开发贡献的读者,可先阅读 README 中的贡献指南,再结合本文提到的 src/composables 与 src-tauri/src/core 源码深入理解各个模块的实现。


从本文可以看到,BongoCat 的"猫咪会跟着你的操作动起来"这一体验,本质上是一条清晰的管道:Rust 侧用rdev/gilrs捕获全局输入 → 通过 Tauri 事件推送到 Vue 前端 → 前端把按键、摇杆、光标坐标映射为 Live2D 参数 →easy-live2d在 Pixi.js 透明画布上实时渲染。理解这条链路后,你不仅掌握了 BongoCat 的完整工作原理,也获得了一套"全局输入驱动透明桌面动画"的可复用架构思路,可以迁移到其它桌面互动应用(如宠物、通知助手、动态图标)的开发中。

  • 桌面应用
  • 前端

【免费下载链接】BongoCat

🐱 跨平台互动桌宠 BongoCat,为桌面增添乐趣!

项目地址:https://gitcode.com/ayangweb/BongoCat
点击查看免费下载

相关推荐

上一篇:深入理解Twilio Video React App的VideoProvider组件:连接管理的终极教程
下一篇:构建下一代AI数字人对话系统:模块化架构的完整实现

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询