ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

如何让猫在菜单栏奔跑?RunCat Neo 菜单栏动画与 CPU 负载速度映射源码解析

如何让猫在菜单栏奔跑?RunCat Neo 菜单栏动画与 CPU 负载速度映射源码解析

【免费下载链接】RunCatNeo

A cute running cat animation on your macOS menubar.

项目地址:https://gitcode.com/gh_mirrors/ru/RunCatNeo
点击查看免费下载

RunCat Neo是一款 macOS 菜单栏应用:一只可爱的小猫在你屏幕顶部的菜单栏里奔跑,而且——它的奔跑速度会实时映射 CPU 负载。CPU 越忙,猫跑得越快。本文带你用最简单的方式看懂它的源码:从 CPU 数据如何采样,到速度公式如何计算,再到 Core Animation 如何让猫"跑起来",全部讲清楚 🐱

它是什么?先看效果

安装 RunCat Neo 后,菜单栏会出现一个动态图标。除了默认的小猫,还内置了小狗、史莱姆、咖啡、牛顿摆、引擎、麻薯等 8 种"跑者"。

更实用的是,点开菜单栏还能看到系统资源面板(CPU / 内存 / 存储 / 电池 / 网络),以及你自定义的指标卡片:

整体架构:CPU 数据如何变成奔跑的猫?

整个数据流只有一条主线,非常清晰:

SystemInfoKit 采样 CPU ──→ RunnerService 计算速度 ──→ AppState 广播 ──→ RunnerLayer 播放动画

RunCat Neo 采用 LUCA 架构,源码分为三层,依赖方向单向:UserInterface → Model → DataSource。本文涉及的三个角色分别在不同层:

角色文件职责
SystemMetricsServiceSystemMetricsService.swift按间隔(默认 5 秒,可选 3s/10s)采样系统信息
RunnerServiceRunnerService.swift把 CPU 百分比换算成奔跑速度
RunnerLayerRunnerLayer.swift用 Core Animation 播放关键帧动画

采样入口在 AppDelegate.swift#L57-L63:AppDelegate启动一个任务组,监听systemInfoStream数据流,每收到一次系统快照,就同时做两件事——刷新资源面板指标、更新猫的奔跑速度。

核心公式:CPU 负载如何映射成速度?

打开 RunnerService.swift#L89-L97,最关键的updateRunnerSpeed(from:)方法只有几行:

func updateRunnerSpeed(from cpuInfo: CPUInfo?) { let cpuValue = max(1.0, min(20.0, Float(cpuInfo?.percentage.value ?? .zero) / 5.0)) let speed: Float = if userDefaultsRepository.speedDecreasesUnderLoad { 0.5 * (21.0 - cpuValue) } else { cpuValue } appStateClient.send(\.runnerSpeeds, speed) }

拆解一下这段"速度映射"逻辑:

  1. 除以 5:CPU 百分比是 0–100,除以 5 后得到 0–20 的区间;
  2. 夹取在 1–20 之间:max(1.0, min(20.0, ...))保证 CPU 为 0 时猫也不停下(最低速度 1),满载时封顶 20 倍速;
  3. 反向模式:如果用户在设置里开启"负载越高跑得越慢"(speedDecreasesUnderLoad),则用0.5 × (21 − cpuValue)取反——CPU 空闲时狂奔、繁忙时慢走,风格完全相反;
  4. 广播出去:结果写入AppState的runnerSpeeds数据流(见 AppState.swift#L35),动画层订阅后即时生效。

对应关系一目了然:

CPU 占用映射速度(默认模式)
0%1(最低速,猫悠闲踱步)
50%10(正常奔跑)
100%20(极限冲刺)

这套行为有完善的单元测试覆盖,例如 50% CPU 对应速度 10、满载对应 20(见 RunnerServiceTests.swift#L230-L265)。

动画原理:为什么不直接换图标?

最直觉的实现是每帧替换菜单栏图标。但 RunnerBarView.swift#L24-L32 的注释记录了一个真实的性能教训:逐帧换图标会让菜单栏在明暗两种外观下对状态项截图,常驻消耗 7–8% CPU;而改用 Core Animation 图层方案后只有约 0.1%。

RunnerLayer.swift 的做法是:

  • 创建一个CAKeyframeAnimation,动画属性是contents(图层内容),calculationMode = .discrete(离散模式,逐帧切换),repeatCount = .infinity无限循环;
  • duration = 帧数 / 2,即 5 帧的猫动画一轮播 2.5 秒(setFrames方法,RunnerLayer.swift#L45-L72);
  • 关键一步在setSpeed(_:)(RunnerLayer.swift#L81-L94):不重做动画,只改图层的speed倍率。通过同步timeOffset与beginTime,可以瞬间变速且画面不跳帧——这就是"CPU 一变,猫立刻加减速"的底层机制。

动画编排:不同角色为什么跑姿不一样?

内置角色的帧序列不是简单 0→1→2→3→4,而是由 FrameOrder.swift#L28-L41 定义:

case .swing: [0, 1, 2, 3, 4, 3, 2, 1] // 麻薯:左右摇摆 case .pendulum: [0, 1, 2, 1, 0, 3, 4, 3] // 牛顿摆:钟摆往复 case .partyHorn: [0, 1, 2, 3, 4, 4, 3, 2, 1] // 史莱姆:号角式回旋

配合 RunnerKind.swift 里每个角色的帧数(猫、狗、史莱姆、水滴、牛顿摆、麻薯各 5 帧,咖啡与引擎 10 帧),就能得到完全不同的"跑姿":猫是匀速前进,麻薯是摇摆,牛顿摆则是钟摆。

打造你自己的跑者

除了内置角色,RunCat Neo 支持自定义跑者:把一组 PNG 关键帧导入,就能让任何角色在菜单栏飞奔(编辑器源码见 CustomRunnerEditorView.swift,自定义帧持久化逻辑在 RunnerService.swift#L121-L136):

此外,它还能监视任意本地 JSON 文件并在面板渲染成卡片(Schema 文档见 CustomMetricsSchema.md),比如接入 Claude Code 状态栏 或 比特币价格。

上手指南:3 步让猫跑起来

  1. 安装:在 Mac App Store 搜索 "RunCat Neo" 安装(要求 macOS 26 或更高版本);
  2. 换角色:点击菜单栏图标,在跑者列表里选猫、狗、史莱姆等,或导入自己的关键帧;
  3. 调手感:在"设置 → 跑者"中可选择"负载高时减速"模式与水平翻转方向,速度映射公式会即时生效。

小结

RunCat Neo 用一条极简的数据流把"系统监控"变成了"桌面宠物":

  • SystemMetricsService负责采样(3/5/10 秒可选);
  • RunnerService负责映射(CPU ÷ 5,夹取在 1–20,可反向);
  • RunnerLayer负责呈现(CAKeyframeAnimation+ 图层speed倍率,全程约 0.1% CPU);
  • FrameOrder负责个性(不同角色的帧编排跑姿)。

想深入更多细节,可以从 ARCHITECTURE.md 开始,它完整描述了三层架构与数据流约定 🚀

【免费下载链接】RunCatNeo

A cute running cat animation on your macOS menubar.

项目地址:https://gitcode.com/gh_mirrors/ru/RunCatNeo
点击查看免费下载

相关推荐

上一篇:小红书数据采集的终极解决方案:5分钟快速上手指南
下一篇:Zotero文献去重终极指南:快速清理重复文献的高效解决方案

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

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进