返回

折叠回忆

把一张旅行照片展开成可以走进的 3D 回忆:照片在环形画廊里滚动、穿过折叠设备的外屏边缘,设备翻开,灯塔、冰山、海边小屋、圣托里尼、大阪城五个场景从屏幕里立起来,可环绕、缩放、倒带;另附可上传壁纸并在浏览器里生成景深的壁纸工作室。

作者: Theodore开源地址
在线体验
折叠回忆在线体验

关于项目

Foldscape Memories(仓库内又名 Nature Memories · Duo)是一个把旅行照片展开成三维回忆的交互展示网站,基于 React、Three.js、GSAP 与 Vite。设备展示的基础来自作者此前复刻的 iPhone Duo 折叠屏浏览器原型(SkentSun / iPhone Duo Depth Lab)——一台内外双屏、七种姿态、两种配色都能动的完整 Mockup;这次在它上面加了「回忆」这一层。

进入首页是一张闭合的设备与一张照片。滚动,候选照片从右侧沿圆柱轨迹进入、穿过外屏边缘溶解进屏幕;点 Open memory,设备用五秒翻开、压低视角,照片里的地方从屏幕里立起来——目前有五段回忆:Round Island Light 灯塔、格陵兰冰海里的红帆船、冰岛 Kálfeyri 的海边小屋、圣托里尼与大阪城。可以拖动环绕、缩放,点 Rewind 沿同一条时间线收回照片。右上角另有独立的壁纸工作室,上传图片或视频换装内外屏,并在浏览器里生成景深。

五个案例的照片与 GLB 模型随仓库保存,展示不依赖任何 API 密钥;可选的浏览器端深度图生成会下载推理模型。项目部署在 Vercel(构建产物 dist/client),仓库 MIT 许可,Apple 官方模型与壁纸资产按 THIRD_PARTY.md 另行声明、不在许可范围内。

体验要点

  1. 首页是一条照片环形画廊:滚轮、拖动或方向键浏览,照片沿圆柱轨迹迁移到设备边缘、以 Melt 噪声溶解进外屏;反向滚动沿同一路径退回,可以停在任意半程。
  2. Open memory 先把选中的照片送到设备、等对应场景模型就绪,再用 5 秒同步展开、压低视角、调整缩放,之后以 4°/秒自动环绕;拖动环绕、滚轮缩放,Rewind 沿时间线反向收回闭合照片。
  3. 五段回忆:Round Island Light 灯塔、格陵兰冰海中的红帆船、冰岛 Kálfeyri 海边小屋、圣托里尼、大阪城——每段都是一张照片加一个 GLB 场景,随仓库分发,浏览无需任何 API 密钥。
  4. 壁纸工作室(?view=wallpaper):上传图片或视频换内外屏壁纸,浏览器里先算快速深度图再由小模型精修,做出随鼠标移动的视差与景深;Star White / Night Sky 两种机身配色;声音默认静音,开启后是程序化海岸声与原创环境和弦;系统「减少动态效果」时关闭场景运动、自动环绕与惯性。

技术解析

  • 3D 资产 · 五个回忆场景 GLB 与 Apple 官方模型改造的折叠设备

    五个回忆各是一张照片加一个 GLB 场景(如 lighthouse-memory-v2.glb 约 25 MB),随仓库保存在 public/scenes 下,运行时只取照片上半部作封面;README 注明展示不需要 Tripo API 密钥——密钥只在制作资产时用到。

    折叠设备来自 Apple iPhone Duo 产品页的官方 USDZ:scripts/prepare-model.mjs 用 Playwright 打开开发页、在浏览器里加载 USDZ,把活动半屏与固定半屏分别命名为 folding-half / stationary-half,内屏与外屏材质换成可替换的白面,再经 GLTFExporter 导出二进制 GLB(贴图上限 512)。机身材质只允许重着色五金框架,屏幕、玻璃、镜头与铰链细节不可改;THIRD_PARTY.md 声明 Apple 资产不在仓库的 MIT 许可范围内。

  • 照片旅程 · 一条 GSAP 进度同时驱动画廊、实体照片与外屏

    环形画廊是 React Bits 的 Circular Gallery 源码从 OGL 移植到 Three.js 的版本:保留 100×50 细分网格、基于速度的正弦顶点波动与圆角图片采样,再扩展为带前后深度与朝向的圆柱路径,与设备共用同一台 PerspectiveCamera。GSAP Observer 接管滚轮、指针与触摸输入及拖动门槛,Timeline 把旅程编排为 approach → receive-and-melt → settle 三段,新输入中断旧动画、拖动可反向采样。

    照片队列、实体照片网格与真实外屏图像由同一个进度驱动,照片在屏幕边缘的纹理坐标一致:外部网格裁掉屏内部分,屏幕补上对应图像。外屏切换用 Morph Slider 的 Melt 分支(intensity 0.95 / scale 4.9 / aberration 0.35),uTime 由旅程进度而非墙钟驱动,所以可以倒带与停帧。

  • 屏幕传送门 · 场景可见范围只由真实的活动屏决定

    场景固定在完全展开后的平面上,不按播放时钟逐帧重建或缩放;能看到多少由活动左屏与固定右屏之间的夹角决定——开盖先释放右屏上方的空间,盖板过垂直、接近平铺时才逐步显露左半,按住盖板不动画面就不动,倒带走的是同一片空间。与活动盖板相交处的临时切面按真实网格交线三角化,做空间剔除、缓存不变平面并复用 GPU 缓冲,用浅冰或中性石色填充,闭合与全开端点隐藏;stencil 方案因交付网格存在开边界被否。左侧水面反射在接近平铺时才淡入,避免倾斜的重影。

    2026-09-16 的启动优化把这套铰链处几何切割搬进 module worker:五个场景原先各需 1–1.6 秒同步准备,现在主线程只做 8–29 毫秒的 transferable buffer 恢复;新挂载的场景先套用当前折叠态再渲染,水面反射相机只拍自然场景不拍设备与画廊,壁纸工作室的预设与 AI worker 推迟到真正进入时才加载。

  • 壁纸工作室 · 浏览器端深度估计与折叠光学细节

    上传的图片先算一张快速深度图,再由小模型精修(@huggingface/transformers 在 depth.worker.js 里运行,AI worker 只在真正点击「开始生成」时创建),前景与背景按深度差位移、虚化,鼠标划过时画面有空间感;五组预设壁纸带 512×288 的预生成景深图,视频预设用海报帧的景深图。内外屏内容层由 JSON 布局与 20 个独立 SVG 图标在运行时合成为透明 GPU 贴图,改单个图标无需重做整张屏。

    折叠本身的细节全在参数里:内外屏的模糊半径系数是 3.5 与 1.8,合盖时外屏先糊、内屏后糊;铰链到 96% 就折到位,最后 4% 留给屏幕「落焦」;亮度沿一条 sin 曲线随姿态压暗,90° 附近最暗;横向视差把屏幕顶点投到一块「完全展开的虚拟平面」上再采样,屏幕几何在折、壁纸却像贴在正前方玻璃上横向滑动,不会歪成梯形。