尧图精选

AIRI 中的 usePreferredReducedMotion:响应式 `prefers-reduced-motion` 媒体查询与无障碍动效降级实践

🕒 发布时间:2026/9/11 5:28:43 📁 来源:尧图网络
AIRI 中的 usePreferredReducedMotion响应式prefers-reduced-motion媒体查询与无障碍动效降级实践【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi本文聚焦 VueUse 浏览器类组合式函数usePreferredReducedMotion讲解其 API 签名、组合式/组件两种用法并结合 AIRIGitHub_Trending/ai/airi仓库中桌面端 Controls Island、移动端自适应布局以及 CSS 层的实际落地展示如何以「JS 响应式 CSS 媒体查询」双轨方案实现可访问性友好的动效降级。一、为什么需要响应式的prefers-reduced-motion许多用户出于前庭障碍、光敏性癫痫或续航考虑会在操作系统中开启「减少动态效果」选项。浏览器随后会暴露 prefers-reduced-motion 媒体查询Web 应用可据此关闭或削弱动画。纯 CSS 方案media (prefers-reduced-motion: reduce)只能作用于样式无法覆盖由 JS 驱动的动画例如Element.animate()、requestAnimationFrame循环、滚动驱动的 Dock 切换需要响应业务逻辑的分支同一个状态变化在「允许动效」与「减少动效」下要走完全不同的代码路径SSR / 初始化阶段服务端渲染或首帧前就需要拿到偏好值做决策。AIRI 仓库内同时存在这两种诉求并在 .agents/skills/vueuse-functions/SKILL.md 中将usePreferredReducedMotion归类为Browser浏览器类组合式函数Invocation规则为AUTO——即在 Vue 3 / Nuxt 3 项目中遇到「减少动态效果偏好」这类需求时应直接选用而不是手写matchMedia监听样板代码。二、API 与用法2.1 组合式 APIComposition API参考 usePreferredReducedMotion.md 的 Usage 与 Type Declarations核心签名如下import { usePreferredReducedMotion } from vueuse/core const preferredMotion usePreferredReducedMotion()返回值是一个ComputedRefReducedMotionType其类型定义export type ReducedMotionType reduce | no-preferencereduce用户开启了「减少动态效果」对应媒体查询prefers-reduced-motion: reduceno-preference用户未做特殊设置对应prefers-reduced-motion: no-preference。函数签名export declare function usePreferredReducedMotion( options?: ConfigurableWindow, ): ComputedRefReducedMotionType要点响应式当用户在运行中切换系统/浏览器动效偏好时preferredMotion.value会随之自动更新配合watch可以即时切换动画行为可选参数options为ConfigurableWindow默认使用window在需要显式传入window或做 SSR 兼容时可传入{ window }无副作用类型声明中标注了__NO_SIDE_EFFECTS__该组合式函数本身不产生外部副作用可安全用于模块顶层或 tree-shaking 场景。2.2 组件 APIComponent Usage除了组合式调用VueUse 还提供了同名渲染组件UsePreferredReducedMotion通过作用域插槽把当前偏好值暴露给模板template UsePreferredReducedMotion v-slot{ motion } Preferred Reduced Motion: {{ motion }} /UsePreferredReducedMotion /template适合在模板层直接根据偏好值做条件渲染例如隐藏装饰性动画元素无需在script setup中额外引入状态。三、AIRI 仓库内的落地实践3.1 桌面端 Controls IslandJS 分支式动效降级在 controls-island-root.vue 中AIRI 桌面端Electron由proj-airi/electron-vueuse提供显示/窗口边界信息的悬浮控件岛会根据窗口位置自动在四个角落之间「搬家」并依赖useTimeoutFn编排leaving → entering → arriving → idle的动效阶段placementLeaveDurationMs、placementEnterPreparationMs、placementArrivalDurationMs分别对应旧角淡出、新角预备、新角进入的时长。关键降级逻辑在relocate()中const preferredMotion usePreferredReducedMotion() function relocate(nextDock: ControlsIslandDock) { stopRelocation() if (nextDock dock.value) { relocationTarget.value undefined motionPhase.value idle return } if (preferredMotion.value reduce) { dock.value nextDock relocationTarget.value undefined motionPhase.value idle return } relocationTarget.value nextDock motionPhase.value leaving finishLeave() }当preferredMotion.value reduce时Dock 直接切换、所有动效定时器被停止控件岛立即出现在目标角落不经过任何过渡阶段。这是纯 CSS 媒体查询无法实现的——切换行为发生在 Vue 组件状态层而不是样式层。3.2 移动端聊天自适应布局跳过 JS 驱动动画在 use-mobile-interactive-area-layout.ts 中AIRI 的移动端聊天区域在软键盘弹出/收起时会调整布局高度并使用 Web Animations APItarget.animate()做 250ms、cubic-bezier(0.32, 0.72, 0, 1)的位移补偿动画规避 Safari 聚焦检查时的输入框错位问题。该动画由 JS 完全驱动CSS 媒体查询鞭长莫及因此通过usePreferredReducedMotion()直接短路watch(keyboardVisible, async (_, __, onCleanup) { const target options.area.value if (!target || preferredMotion.value reduce) return // ... 计算位移 offset 并执行 target.animate(...) }, { flush: sync })同时在onScopeDispose(() areaAnimation?.cancel())中清理动画避免内存泄漏。这展示了一个通用模式凡是用 JS API 驱动的动效都应以preferredMotion.value reduce作为前置守卫。3.3 CSS 层降级media (prefers-reduced-motion: reduce)对于纯 CSS 动画AIRI 使用标准媒体查询兜底形成「JS 守卫 CSS 兜底」的双保险onboarding.vue引导页滑入滑出动画在减少动效时被压缩为1msaction-menu/index.vue聊天操作菜单同类处理animated-content.vue通用内容动画在reduce下直接animation: none。三者分别覆盖「组件库动效stage-ui」「基础 UI 包ui」与组合式函数层面的 JS 守卫互补CSS 管样式动画usePreferredReducedMotion管 JS 逻辑分支。四、最佳实践小结JS 驱动的动效优先在relocate()/watch等逻辑入口检查preferredMotion.value reduce直接走无动画路径CSS 驱动的动效保留media (prefers-reduced-motion: reduce)规则参考上述三处实现将动画时长设为1ms或animation: none状态响应不要只在初始化时读取一次应把preferredMotion作为响应式来源接入computed/watch用户中途切换偏好时行为即时生效模板场景需要按偏好渲染内容时使用UsePreferredReducedMotion组件的作用域插槽v-slot{ motion }保持script干净。usePreferredReducedMotion的接入成本仅一行代码却能保证 AIRI 在用户开启系统级「减少动态效果」后桌面控件岛、移动端聊天区等核心交互依然可用且不再产生诱发不适的动画——这是 Web 无障碍A11y实践中「多入口、双轨降级」的典型范式。【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →