发布时间:2026/8/23 8:32:37
Rust + Tauri实现一棵「习惯树」:创意应用--习惯可以成参天大树 我花了两天时间把一款钟爱的设计理念用 Rust Tauri 实现了。坚持不必是枯燥的对勾与数字——它把每一次坚持可视化成一棵基于分形算法生成的「习惯树」让坚持本身成为一种值得期待的小仪式。 这篇文章聊聊为什么想做它以及背后的原理和实现思路。好习惯改变一生。好习惯陪伴一生。习惯树是一款完全本地运行的习惯养成应用。坚持不必是枯燥的对勾与数字——它把每一次坚持可视化成一棵基于分形算法生成的「习惯树」让坚持本身成为一种值得期待的小仪式。 开发缘由好习惯值得一棵树我们都明白「习惯成自然」的道理但真正把一件小事日复一日地做下去并不容易啊。有多少人能够克服阻力坚持下去但如果你每次的努力都能有反馈和惊喜呢用过的习惯 App 不少可大多数是「打卡按钮」——每天机械地按一下久了之后打卡本身反而成了一种负担。也试过Habitica 那种游戏化的养成系统很完整但对只想安静坚持的人来说稍显复杂。于是我想我需要的不是又一个待办清单而是一点仪式感——一个让坚持本身变得值得期待的东西。坚持有了形状也就有了仪式感。习惯树把每一次坚持具象成一棵基于分形几何算法、不断生长的「习惯树」打卡模式养成好习惯每日健身、早睡早起。每完成一次任务 小树就长高一点、多分几个叉最终长成一棵茂盛的大树——树上的每一片枝叶都是你努力的证明。戒断模式戒掉坏习惯戒酒、戒烟。你只需要坚持「不做」小树就会自己生长一旦忍不住破了戒就去记录「复发」的时间和原因然后亲眼看着自己培育的树苗枯萎回一颗种子——这种眼睁睁看着亲手培育的植物凋零的挫败感比任何单纯的警告都更有效。开源地址https://gitcode.com/qq8864/habit-tree截图缘起从「打卡焦虑」到「想看一眼那棵树」我是习惯养成类 App 的重度用户但一直卡在一个尴尬的位置。传统打卡 App 的问题在于打卡这个动作慢慢变成了一种负担。每天早上点一下「完成」久了之后你分不清自己是在培养习惯还是在给日历上色。Habitica 那套把习惯变成 RPG 养成很有意思但对我这种只想安静坚持的人来说太庞大了——装备、任务、副本我只是想记住「今天该跑步了」。直到我发现了 Grove。它把坚持具象成一棵分形算法生成的树打卡模式每完成一次小树就长高一点、多分几个叉戒断模式你只要什么都不做树就自己长大一旦破戒你得亲手记录复发的原因然后眼睁睁看着树枯萎回一颗种子这个设计击中了我它把「坚持」变成了「想看看今天它长什么样」的期待而不是又一个待办。它还很精致——Material You 动态取色、四种卡片布局尤其是那个 3D 滚筒布局上下滑动时卡片像唱片一样转过去配合线性马达的震动每次操作都很解压。Grove 是 GPL-3.0 开源的数据格式、成长机制、树形算法都是公开的。于是我想与其天天夸它不如自己动手用 Rust Tauri 造一个属于我的版本。不是要替代谁是想借这个项目把「习惯追踪」这个领域里最好的设计拆开看明白。 彩蛋东风夜放花千树东风夜放花千树更吹落、星如雨。玉壶光转一夜鱼龙舞。——《青玉案·元夕》辛弃疾生活需要仪式感为了让生活更有仪式感为了让这个小而美的APP更加有趣有新引力当然为了让你更能养成好习惯想到了一个好创意连续打卡达成生长阶段7 天 / 30 天 / 90 天…时里程碑动画自动绽放想象这么一首东风夜放花千树的景象夜色与星光中你的习惯树自下而上逐层亮起彩灯花千树烟花升空爆散火花如星雨坠落满月升起玉壶光转发光灯龙蜿蜒游过一夜鱼龙舞最后以词句落款成一张可一键保存的卡片。可以将这个“纪念勋章”一样的东西保存起来发个朋友圈作为自己努力的见证形成一种潜在的正向激励不断鼓励自己坚持下去养成一个好习惯无论是看书也好跑步也罢对自己终身受益。 仪式感不止于此生活需要仪式感。这也是习惯树的底色——我们想打造一款小而美的精品习惯应用不追求大而全的功能堆砌专注把「坚持」这件小事做得有温度、有惊喜。规划中的仪式感彩蛋敬请期待节日应景根据节日变换氛围——春节的万家灯火、中秋的玉壶月影、元宵的花千树灯海都会在应景的时节悄悄登场开盲盒达成特殊条件时开启仪式感盲盒——专属树形皮肤、限量徽章、词句笺等小礼物为坚持添一份不确定的期待️隐藏彩蛋不定期埋入的小惊喜藏在界面的某个角落等你发现功能特性分形习惯树每棵树由确定性种子生成同一棵树在任何平台渲染结果一致从种子到参天大树经历 5 个生长阶段1/7/30/90 天阶段内渐进生长里程碑彩蛋「东风夜放花千树」达成生长阶段7/30/90 天…时播放节日庆典动画——分形树逐层亮起彩灯、烟火如星雨坠落、玉壶满月升起、灯龙游过词句落款卡片可一键截图分享每阶段仅一次可跳过、可关闭双追踪模式打卡模式每日任务与戒断模式戒掉习惯破戒触发枯萎动画把「失去」做成视觉反馈四种卡片布局3D 滚筒核心卖点滚动带旋转景深与聚焦光环、横向轮播、双列网格、紧凑列表一键切换完整打卡管理月历五态视图打卡/请假/复发/今天/未来、补记历史日期、修改打卡时间、请假不中断连续、冻结连续、每日备注Material You 动态主题种子色一键换肤浅色/深色模式默认森林绿隐私优先零权限、零联网、零账号数据仅存本机%APPDATA%\com.grove.habittrees\grove.redb备份兼容导出/导入 Grove 兼容 JSON 备份原版数据可直接迁移本地化界面为简体中文适应中文用户习惯技术栈层选型桌面框架Tauri 2Rust WebView2后端Rustserde / chrono存储redb纯 Rust 嵌入式 KV零 C 编译前端TypeScript Vite无框架Canvas 分形树渲染测试Rust 单元测试 13 个派生统计 存储架构┌─ 前端Tauri WebView────────────────────────┐ │ TypeScript Canvas 渲染 │ │ 四种布局 / 日历 / 弹层 / 主题 │ └───────────────┬── invokeJSON 契约─────────┘ ┌───────────────▼───────────────────────────────┐ │ Rust 后端 │ │ 派生统计纯函数 单测 │ │ redb 存储id → 整棵树 JSON │ │ 5 条命令list / upsert / delete / export / import │ └───────────────────────────────────────────────┘领域逻辑连续天数、生长阶段、请假/冻结规则全部在 Rust 端以纯函数实现前端只负责渲染JSON 契约与 Grove 备份格式一致camelCase保证备份文件双向兼容。第一阶段先画原型别急着写代码动手之前我先从 Grove 的源码里拆出了两样「宝贝」。第一样是数据模型。整个 App 的核心就一个结构体名称、ARGB 颜色、起始日期、复发列表、打卡日期集合、请假日、打卡时间戳与备注外加一个决定树形态的geneticSeed。所有派生数据——连续天数、最佳纪录、生长阶段——都是从这个结构算出来的而且全部是纯函数输入一棵树和今天的日期输出全部统计没有副作用没有内部状态。第二样是分形树渲染器。一个 31KB 的绘制文件藏着整棵树的秘密树的 DNA 由种子确定性生成从 0 到 5 层递归分支叶簇、树皮刻痕、树冠飘动的孢子还有打卡时的生长爆发粒子。同一个种子在任何平台上画出来都是同一棵树。我照着这两样先做了一个单文件 HTML 交互原型——四个布局、种树、打卡、请假、破戒枯萎动画、Material You 主题全部能点能玩。原型阶段验证了一件事这套交互和算法用 Web 技术完全能还原值得投入正式实现。原理一连续天数到底是怎么算的习惯追踪的核心是「连续」streak。听起来简单细想全是边界条件今天没打卡昨天的连续还算不算规则最新记录距今天超过 1 天连续清零出差请了假请假那天算不算连续有个开关请假「计入连续」或「只保不增」两种策略断更了但之前冻结过还要不要清零冻结 断更不清零但也不再增长戒断模式和打卡模式完全相反戒断是「距离上次破戒的天数」而打卡是「连续打卡的天数」我把原版算法逐行翻译成 Rust每个分支都配了单测阶段边界1/7/30/90 天、连续中断、请假两种策略、冻结、破戒重置、导入数据的日期格式容错——13 个测试把行为钉死以后改代码不怕改出偏差。这个「数据 纯函数」的架构是整件事的地基。前端不自己算统计它只负责渲染每次数据变更后调 Rust 拿最新的派生结果。统计逻辑只有一份、在 Rust 里、有测试护着永远不会出现「界面显示的连续天数和数据库对不上」这种烂账。原理二一棵树是怎么「长」起来的这是整个项目最漂亮的部分值得展开讲讲。确定性种子。每棵树创建时生成一个随机种子之后一切形态都由它决定。种子经哈希映射出 8 个 DNA 参数——主干倾斜、分叉展开角、枝长衰减率、分叉高度、叶密度、叶形……还从 4 种「树型原型」里挑一种有的树喜欢往上蹿有的树爱横向铺开。同一颗种子永远长出同一棵树所以树的形态可以放心存、放心恢复不用序列化任何几何数据。递归分支。渲染从根部开始主干按角度和长度画一笔然后在顶端分叉成两个子枝子枝长度按比例衰减、角度加随机扰动继续递归。生长阶段决定递归深度——种子 0 层、嫩芽 2 层、树苗 3 层、小树 4 层、参天大树 5 层。层数越多树冠越丰满。渐进生长。光有阶段跳变是不够的——一棵树从「种子」直接变成「嫩芽」会显得很生硬。所以阶段内部还有一个 0 到 1 的进度值主干的长度、展开角、粗细都随进度线性插值。连续天数从 1 天涨到 90 天树是肉眼可见地一点点长起来的而不是某天早上突然换了一棵。颜色与细节。树皮、树叶、高光都不是单独的调色板而是从用户选的主色派生出来的——树干压暗、树叶提亮、叶尖再提亮一点整个树自然就有体积感。叶簇由多层贝塞尔叶片叠加大树还有飘浮的孢子和苔藓团加上风的相位参数整个树冠在缓慢呼吸。两个情绪时刻。打卡成功时枝端会喷出一圈粒子叶片加光晕是「成长」的正反馈破戒时树叶飘落、树干倾倒枯萎再重置回一颗种子——把「失去」做成一种视觉惩罚。这两个动画是 Grove 设计的灵魂我原样保留了自己的实现。原理三架构与数据流动┌─ 前端Tauri WebView────────────────────────┐ │ TypeScript Canvas 渲染 │ │ 四种布局 / 日历 / 弹层 / 主题 │ └───────────────┬── invokeJSON 契约─────────┘ ┌───────────────▼───────────────────────────────┐ │ Rust 后端 │ │ 派生统计纯函数 单测 │ │ redb 存储id → 整棵树 JSON │ │ 5 条命令list / upsert / delete / export / import │ └───────────────────────────────────────────────┘几个关键设计决策前后端各管各的。领域逻辑统计、校验全在 Rust前端只管画。Tauri 的 invoke 是天然的契约边界JSON 字段统一成驼峰命名。存储选型踩过坑。一开始用 SQLite结果撞上这台机器 MSVC 工具链选择的坑vswhere 失效导致 Rust 误选了一个古董 VS2015 链接器release 构建时 SQLite 的 C 代码报出 CRT 导入符号未解析。关键是tauri build的子进程环境我完全控制不了修了多轮都不稳定。最后换成 redb——纯 Rust 的嵌入式数据库零 C 编译。对「单用户、几十棵树的 JSON 存储」这个场景它完全够用还顺带把一整类「C 代码 × MSVC 工具链」的脆弱性从根上删掉了。换成之后构建一次通过安静得像什么都没发生过。双后端适配。前端的存储层做了两层实现浏览器里用 localStorage mock方便自动化回归Tauri 里走真实 invoke。开发时在普通浏览器里就能跑完整流程调试 UI 不用每次起桌面窗口。高光时刻当「Smoking · 已坚持 247 天 · 参天大树」和「Alcohol · 80 天 · 小树」出现在我自己的应用里时那种感觉挺奇妙的——真实用户的数据跨过 Flutter 和 Rust 的鸿沟在一棵由我写的代码渲染出来的分形树上继续生长。这大概是「兼容性」这个词最有成就感的样子。途中踩过的三个坑字段名的大小写之争。原型阶段图省事用了下划线命名移植到 TypeScript 时保留了这个习惯而 Rust 模型为了兼容备份格式用了驼峰。两边各说各话invoke 反序列化静默失败界面上只弹一个笼统的「操作失败」。修法不复杂——统一成驼峰让类型系统把所有的check_in_days改成checkInDays——但这类「两个语言约定不一致」的坑跨端项目里简直是家常便饭。现在我把 JSON 契约写死在类型定义里谁都不许私自改名。一个负数颜色的诡异事故。报错信息很有意思invalid value: integer -8622120, expected u32。我明明存的是#7C6FD8怎么成了负数凶手是 JavaScript 的位运算0xff000000 | 0x7c6fd8会把结果强制转成有符号 32 位整数于是 42 亿多的正数变成了负数。改一行算术加法就好但教训值得记住跨语言传颜色别跟 JS 的位运算较劲。「同样的命令为什么它不行」。就是上面提到的 MSVC 工具链问题。最崩溃的是同样的 cargo 命令我手动敲能过tauri build就是不行——子进程的环境我完全拦截不到试了包装 cargo、注入环境变量、改链接器路径全被无声地绕开。最后的选择是换掉数据库从问题域上删除它而不是继续和工具链搏斗。这也算一种工程智慧当你在某个层面反复受挫退一步问「我是不是可以不经过这个层面」。现状与下一步现在的状态后端Rust redb13 个单测守护全部业务逻辑构建一次通过前端TypeScript Vite无框架分形树渲染器 四种布局 日历 枯萎动画数据与 Grove 备份格式双向兼容导出即原版格式交付NSIS 安装包和 MSI 都已产出双击即装M2 的清单还排着系统通知和里程碑提醒、中英文国际化、树快照分享。不过说真的最想做的其实是那个滚筒布局的桌面版——在宽屏上把几棵参天大树排成一排转起来应该比手机端还好看。生活需要仪式感。这也是习惯树的底色——我们想打造一款小而美的精品习惯应用不追求大而全的功能堆砌专注把「坚持」这件小事做得有温度、有惊喜。

相关新闻

2026/8/23 8:32:37

广深莞定制纸箱批量采购:综合成本与隐性物流成本核算指南

标题:广深莞定制纸箱批量采购:综合成本与隐性物流成本核算指南目标简述帮助广深莞地区工业企业全面核算定制纸箱采购的综合成本,识别显性单价之外的隐性物流、仓储、质量损耗成本,建立全周期成本评估模型,实现采购成本…

2026/8/23 9:32:41

磁盘性能优化:深入理解顺序读写与随机读写的原理与实践

1. 从一次磁盘告警说起:理解IO性能的紧迫性那天下午,监控系统突然弹出一条刺眼的告警:“服务器磁盘使用率超过90%”。我心头一紧,这可不是小事。登录系统一看,/data分区一片飘红。常规操作——清理日志、删除临时文件—…

2026/8/23 9:32:41

基于MiniMaxH3与ComfyUI的AI视频处理工作流:从部署到高清生成实战

1. 先搞清楚这个工作流到底能帮你做什么如果你正在找一套能自动处理视频、提升画质、还能生成新视频的工具,这个基于 MiniMaxH3 和 ComfyUI 的工作流值得你花时间研究。它不是一个单一功能,而是一个打包好的“视频处理车间”,核心目标是解决两…

2026/8/23 9:32:41

Java高并发面试核心考点与实战解析

1. 高并发面试核心考察点解析在Java高并发领域的面试中,面试官通常会从三个维度考察候选人的真实水平:理论基础深度、实战经验广度和系统设计高度。我参与过近百场技术面试后发现,90%的高频问题都围绕以下核心展开:并发编程基础&a…

2026/8/23 9:32:41

WinForm TabControl美化实战:从原生控件到现代化UI的三种方案

1. 项目概述:为什么WinForm TabControl需要“美化”?如果你和我一样,是从WinForm桌面开发那个年代一路走过来的,看到“TabControl美化”这个标题,心里大概会泛起一丝苦笑。微软自带的那个灰底白字、方方正正的TabContr…

2026/8/23 0:02:04

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/23 0:02:04

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/23 0:02:04

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/23 0:02:04

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/23 0:02:04

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/23 0:02:04

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/21 15:40:01

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/23 6:14:43

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/23 4:22:01

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…