ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

滚出屏幕即冻结、减弱动效用户看静态帧:thinking-orbs藏在Canvas加载动画里的无障碍与性能最佳实践

滚出屏幕即冻结、减弱动效用户看静态帧:thinking-orbs藏在Canvas加载动画里的无障碍与性能最佳实践 滚出屏幕即冻结、减弱动效用户看静态帧thinking-orbs藏在Canvas加载动画里的无障碍与性能最佳实践【免费下载链接】thinking-orbsDotted thought-orb loading indicators for AI agent UIs, 9 tuned types, two sizes, auto dark/light项目地址: https://gitcode.com/gh_mirrors/th/thinking-orbsthinking-orbs 是一个专为 AI 与 Agent 界面打造的 Canvas 加载动画组件它用纯 2D canvas 绘制 9 种手工调优的思考光球动效提供 64px 与 20px 两档独立调参的尺寸并自动适配深色/浅色主题。除了好看它更值得学习的地方在于细节工程——滚出屏幕自动冻结动画、尊重系统减弱动态效果设置、所有实例共享同一时钟、DPR 封顶等无障碍与性能最佳实践。这篇文章带你逐个拆解这些藏在代码里的设计。为什么一个小小的加载动画值得讲究性能聊天界面里常见的做法是一个 GIF 或者 CSS 动画一直转、一直消耗帧率。当页面里同时挂着十几个 AI 会话状态时这些看不见的动画仍在持续跑着requestAnimationFrame白白吃掉主线程和 GPU。thinking-orbs 的解法很朴素看不见的动画不跑。❄️滚出屏幕即冻结组件内部用IntersectionObserver监听自身是否在视口内。滚出屏幕的瞬间立刻cancelAnimationFrame滚回来再恢复标签页切到后台visibilitychange同样暂停。实现就藏在这几十行里src/ThinkingOrb.tsxconst io new IntersectionObserver(([entry]) { visible entry.isIntersecting; if (visible document.visibilityState ! hidden) start(); else stop(); }); io?.observe(canvas);⚡️共享时钟所有实例同相位恢复更巧妙的一点每个实例虽然有各自的 rAF 循环但时间戳统一取自performance.now()而不是各自的局部计时器。这意味着冻结再恢复时所有光球依然同相位——不会出现滚回来之后各转各的违和感。时钟与循环的衔接逻辑见时钟与帧函数src/ThinkingOrb.tsxstart/stop 控制src/ThinkingOrb.tsx减弱动效用户看静态帧prefers-reduced-motion 的正确打开方式♿️ 不少动效组件对减弱动态效果设置的处理是干脆渲染一个空白或纯色圆点。thinking-orbs 的做法更讲究——渲染一帧确定性的代表帧通过matchMedia((prefers-reduced-motion: reduce))实时订阅系统偏好用户中途切换也能即时响应见 src/theme.ts命中该偏好时不调度任何动画循环只调用一次绘制函数frame(0.6)停在光球最有辨识度的那一刻见 src/ThinkingOrb.tsx这个0.6并非随意取值——它恰好是项目回归测试工具采用的第一组冻结时间戳FREEZE_TIMES [0.6, 1.7, 3.3, 5.1]说明代表帧是经过跨状态、跨尺寸验证过的构图时刻见 demo/parity.ts。静态帧还会继续跟随实时主题变化深浅色切换不会失效。低端设备友好只用最便宜的 2D 绘制性能预算的第二层花在绘制管线上。项目在 src/engine/core.ts 的注释里写得很直白Plain 2D canvas fills only: no ctx.filter, no SVG filters, no WebGL — every mode renders identically in Chrome, Safari and Firefox.无 WebGL、无滤镜深度感完全靠点的大小和墨色深浅表达src/engine/core.ts三大浏览器像素级一致低端设备上成本极低DPR 封顶 2Math.min(2, devicePixelRatio)避免 3x 屏幕上把 64px 画布开到 192px 的浪费见 src/ThinkingOrb.tsx预设速度是烘焙好的9 种状态 × 2 档尺寸各自有独立的速度、点数、点径调参渲染循环里只乘一个系数无运行时开销见 src/presets.ts无障碍不只是动效降级 屏幕阅读器用户需要的不是动画而是语义。组件在 src/ThinkingOrb.tsx 里给 canvas 挂了roleimg并按状态内置了 9 个默认aria-label如 searching 对应 Searching…见 src/ThinkingOrb.tsx同时支持aria-label属性覆盖让开发者可以写更贴业务的描述。快速上手安装与最小用法都很轻npm install thinking-orbsimport { ThinkingOrb } from thinking-orbs; ThinkingOrb statesearching size{64} /theme默认auto会自动读取祖先节点的data-theme/dark/light类名与系统深浅色全程零配置。更多属性speed、paused、aria-label等可参考 src/types.ts。小结把看不见的工程做好实践用户收益IntersectionObserver 滚出即冻结后台标签更省电、帧率更稳共享时钟performance.now()恢复动画时所有实例同相位prefers-reduced-motion 静态代表帧前庭障碍用户不晕、信息仍在纯 2D DPR 封顶 2低端设备、高分屏成本可控roleimg 状态化 aria-label屏幕阅读器能读懂它在做什么一个 64px 的加载动画藏着完整的无障碍与性能思维。如果你想在自己的 Canvas 组件里复刻这些做法thinking-orbs 的 src/ThinkingOrb.tsx 与 src/theme.ts 是值得逐行阅读的轻量范本。【免费下载链接】thinking-orbsDotted thought-orb loading indicators for AI agent UIs, 9 tuned types, two sizes, auto dark/light项目地址: https://gitcode.com/gh_mirrors/th/thinking-orbs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表