惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
B
Blog RSS Feed
Microsoft Azure Blog
Microsoft Azure Blog
J
Java Code Geeks
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Google DeepMind News
Google DeepMind News
F
Fortinet All Blogs
V
V2EX
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Engineering at Meta
Engineering at Meta
月光博客
月光博客
阮一峰的网络日志
阮一峰的网络日志
M
MIT News - Artificial intelligence
IT之家
IT之家
博客园 - 【当耐特】
U
Unit 42
云风的 BLOG
云风的 BLOG
L
LangChain Blog
小众软件
小众软件
Microsoft Security Blog
Microsoft Security Blog
B
Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
宝玉的分享
宝玉的分享
N
Netflix TechBlog - Medium

博客园 - 卢布

工作感受月记(202609月) About Myself - Explorer Club Speech 工作感受月记(202608月) 【散文】人类将继续向前,永不停止 ——《AI启示录:奇点降临》读后感 工作感受月记(202607月) 挂树风筝,随风而漂——《一个男人和一个女人》 给阿嬷的情书 编码者卢布 · 个人简介 工作感受月记(202606月) 工作感受月记(202605月) 工作感受月记(202604月) 工作感受月记(202603月) 工作感受月记(202602月) 工作感受月记(202601月) 工作感受月记(202512月) 工作感受月记(202511月) 工作感受月记(202510月) 工作感受月记(202509月) 工作感受月记(2025年08月) 工作感受月记(202507月) 工作感受月记(202506月) 工作感受月记(202505月) 工作感受月记(202504月) 工作感受月记(202503月) 看 (秘密)之所悟 工作感受月记(202502月) 回家之难难于蜀道难 工作感受月记(202501月) 工作感受月记(2024年12月) 工作感受月记(202411月)
【MetaMe】通过vibe coding构建的元我虚拟空间
卢布 · 2026-08-28 · via 博客园 - 卢布

一个 .NET 8 + Three.js 的 vibe coding 实验:从"卡片式首页"到"程序员坐在宇宙里敲代码"。


一、为什么需要一个 3D 首页?

MetaMe 从一开始就不是一份简历,也不是作品集,而是一个关于"我"本身的可展览作品。项目文档里把它定义为:

Meta = 元 / 关于自身,Me = 我。中文名"元我",英文 MetaMe。
它是职业身份、生活身份、思想身份三层切面的集合。

既然网站本身是一个"自画像",那么首页就不该只是文字、图片和按钮的堆砌。它应该像走进一个人的客厅一样——你看见他的样子、他的工作台、他关心的话题,以及通往不同房间的入口。

这个直觉推动了 3D 首页的诞生。


二、项目构思:一个坐在虚拟空间里敲代码的人

设计目标非常具体:

  1. 中心是一位低多边形程序员——戴着耳机、眼镜,坐在桌前敲笔记本,屏幕上代码滚动。
  2. 周围漂浮着属性气泡——"客户问题解决者"、"技术顾问"、"根因分析师"等身份标签,以及"计算"、"数据"、"网络"等技术领域。
  3. 远处有传送门入口——对应网站的栏目:看、做、写、我、年表、现在。点击即跳转。
  4. 所有内容可后台编辑——不是写死在前端,而是从 Data/singletons/home.json 读取,并通过 /admin 单例编辑器维护。

当前 3D 首页效果


三、Vibe Coding 过程:不是一次设计,而是三轮迭代

第一轮:从"气泡环绕"开始

最初的指令是:"在页面中构建一个虚拟的程序员人物形象,在他周边以气泡状显示各种自画像属性。"

于是我们有了:

  • 一个由基础几何体拼出来的低多边形程序员(Box + Cylinder + Torus)。
  • 他坐在圆台上,前方有发光的笔记本电脑屏幕。
  • 周围用 THREE.Sprite 漂浮着 10 个气泡,分两类:
    • role:大、内圈、高不透明,代表核心身份。
    • tag:小、外圈、低透明,代表技术领域。
  • 六个传送门环绕成环,作为栏目入口。

这一阶段完成了"空间感"。

首页变成全屏,header 不再是顶部一条白底导航,而是浮在 3D 空间上方的透明层。滚动到下方纸面内容后,header 再变成暗色毛玻璃。

这一步让网站从"页面"变成了"空间"。

第三轮:分层信息架构 + 悬停介绍

最新的需求把空间信息做了更明确的分层:

  • 第一圈(中心附近):3 张身份卡片,围绕中心点缓慢公转。第 1 张是主身份卡(带头像、昵称、tagline),后两张分别是"我能做什么"和"我的信条"。
  • 外圈:6 个传送门,文字直接写在圆盘中心点,始终面向相机。
  • 最底层:所有小属性标签(包括 role 和 tag)统一缩小、贴近地面、低透明,作为环境信息沉底。
  • 悬停介绍:鼠标停留在身份卡、气泡或传送门上时,出现玻璃质感的 tooltip,显示标题和描述。

悬停 tooltip 效果

这一步把"信息层级"和"可探索性"做扎实了。内容不是一眼看完的,而是可以逛的。


四、技术实现要点

1. 自托管 Three.js,无 CDN

项目里 wwwroot/js/lib/three.module.min.js 是自托管的 Three.js r160,通过 importmap 引入。这样不依赖外部 CDN,符合"数据主权"和"无厂商依赖"的设计原则。

2. 全部画面元素用 CanvasTexture 动态绘制

身份卡、气泡、传送门文字都不是图片,而是用 HTML Canvas 动态绘制成纹理:

  • 身份卡的圆角边框、头像圈、昵称、tagline。
  • 气泡的底色、边框、小圆点和标签文字。
  • 传送门的发光圆盘和中文/英文双语标签。

这样做的好处是:内容改了,纹理自动重绘,不需要重新出图。

3. 数据驱动:后端 JSON 注入前端 CONF

Pages/Index.cshtmlhome.json 里的 space 节点序列化后注入为页面上的 <script id="hero3d-config">

{
  "idCards": [
    { "title": "元我 · 虚拟身份卡", "description": "..." },
    { "title": "我能做什么", "description": "..." },
    { "title": "我的信条", "description": "..." }
  ],
  "bubbles": [
    { "label": "客户问题解决者", "kind": "role", "description": "..." },
    { "label": "技术顾问", "kind": "role", "description": "..." },
    ...
  ],
  "portals": [
    { "key": "看", "description": "..." },
    ...
  ]
}

home-3d.js 读取 CONF 动态生成场景。内容变更只需要改 JSON,不需要碰 JS。

4. Raycaster 实现悬停与点击

THREE.Raycasterpointermove 时检测:

  • 是否命中身份卡 → 显示 tooltip。
  • 是否命中气泡 → 显示 tooltip。
  • 是否命中传送门 → 整组高亮 + tooltip,点击后触发 warp 跳转。

Tooltip 是普通的 DOM <div class="hero3d-tip">,根据鼠标位置定位,并做视口边界裁剪。

5. 动画与性能控制

  • 人物呼吸、头部微动、前臂打字动画。
  • 身份卡和气泡的公转 + 上下浮动。
  • 传送门圆盘自转、发光强度脉动。
  • 尊重 prefers-reduced-motion
  • DPR 限制为 ≤2,标签页隐藏或滚出视口时暂停渲染。

五、踩过的坑

1. 端口与进程冲突

多次 dotnet run 后,残留 Kestrel 进程占住端口(5199、5200、5210、5220、5230……),导致新实例起不来。解决方式:每次开发完用 taskkill 清理,或者换用新端口。

2. Windows 文件锁

dotnet buildMetaMe.exe 经常被运行中的 Kestrel 进程锁住。必须先杀进程再编译。这是 Windows 开发 .NET 应用的常见痛。

3. safe-delete 包装器

清理项目时,本机的 rm 和 PowerShell Remove-Item 都被一个 safe-delete 包装器拦截,统一走回收站。而回收站 API 对部分文件/目录报"这个系统不支持该功能",导致删除失败。

绕过方法:find <path> -delete(直接 unlink,不经过回收站)。

4. JsonContentStore 索引重建失败

Windows 下 File.Move(overwrite:true) 覆盖 data/indexes/posts.json 会报 AccessDenied。修复方式:先 File.DeleteMove,失败时回退为直接 File.WriteAllText;同时 RebuildIndexes() 用 try/catch 包裹,避免启动崩溃。


六、当前效果总结

打开首页,你会看到:

  • 一名低多边形程序员坐在宇宙中央的圆台上,笔记本屏幕代码闪烁,桌面上方悬浮着全息终端。
  • 3 张身份卡环绕他缓慢公转,分别回答"我是谁"、"我能做什么"、"我相信什么"。
  • 外圈 6 个发光传送门,上面写着"看 / 做 / 写 / 我 / 年表 / 现在",点击即可进入对应栏目。
  • 地面附近漂浮着小属性标签:"客户问题解决者"、"技术顾问"、"根因分析师"、"计算"、"数据"、"网络"……
  • 鼠标悬停在任何元素上,都会出现一个玻璃质感的介绍窗口。
  • 拖动旋转视角,Ctrl+滚轮缩放,移动端支持单指旋转和双指缩放。

七、下一步

3D 空间的骨架已经搭好,接下来是内容:

  1. 替换占位头像和昵称,接入真实的 profile.json
  2. 填充真实作品,让"看 / 做 / 写"传送门背后有东西可点。
  3. 把 3D 首页的加载性能再压一压(目前首屏已不算重,但仍有优化空间)。
  4. 上 Azure App Service 部署,挂载 Azure Files 持久化 /data

这个首页的终极检验标准来自需求文档里的一句话:

让一个陌生人在 10 秒内产生"这人有点意思"的判断。

3D 空间不是炫技,而是为了让"有点意思"这个判断,在第一眼就发生。


2026-08-27 · MetaMe 3D 首页开发记录