airi 前端实战:深入解析 VueUse useParallax 视差传感器组合式函数
2026/9/10 14:44:28 网站建设 项目流程

airi 前端实战:深入解析 VueUse useParallax 视差传感器组合式函数

【免费下载链接】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-sama's altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi

useParallax是 VueUse 库中位于 Sensors(传感器)分类下的组合式函数,它用最少的代码即可为 Vue 组件接入"随设备倾角或鼠标移动而偏移"的视差效果。本文以 airi 仓库中 vueuse-functions 技能集 的 useParallax 参考文档 为主体,结合仓库内 VueUse 14.4.0 的依赖配置与相关组合式函数的参考实现,系统讲解其返回值、配置项、底层传感器回退机制,并给出可在 airi 各 Web 应用中直接落地的完整示例。读完本文,你将能够在任意 Vue 3 组件中快速实现"设备陀螺仪 + 鼠标"双模视差层,并掌握如何通过adjust回调精确控制每一轴上的偏移幅度。

useParallax 是什么:Sensors 分类下的视差组合式函数

useParallax的目标是"轻松创建视差效果"(Create parallax effect easily)。它底层复用两个更基础的传感器组合式函数:

  • 优先使用useDeviceOrientation(设备物理朝向,即陀螺仪数据);
  • 当设备方向(deviceorientation)事件不可用时,自动回退到useMouse(鼠标位置)。

这种"高能力传感器优先、低能力传感器兜底"的设计,让同一套代码既能覆盖桌面端鼠标交互,又能覆盖移动端手机倾角交互,而调用方完全无需关心设备差异。

在 airi 仓库的 vueuse-functions 技能集 中,useParallax被归入Sensors分类,其 Invocation 规则为AUTO——即只要在 Vue.js / Nuxt 开发中遇到视差需求,就应优先考虑使用它,而不是手写事件监听与计算逻辑。技能集给出的选型原则是"能用组合式函数解决的,就不要写自研代码",useParallax正是这一原则在交互动效领域的典型代表。

仓库的 pnpm-workspace.yaml 中声明了全局依赖目录:

'@vueuse/core': ^14.4.0 '@vueuse/motion': ^3.0.3 '@vueuse/shared': ^14.4.0

也就是说,airi 下所有引用catalog:版本的应用与包(如 apps/stage-web、apps/stage-tamagotchi、apps/stage-pocket、packages/stage-ui 等)都能直接import { useParallax } from '@vueuse/core',无需额外安装依赖。

快速上手:三行代码接入视差

参考文档给出的最小用法如下:

<script setup lang="ts"> import { useParallax } from '@vueuse/core' const container = ref(null) const { tilt, roll, source } = useParallax(container) </script> <template> <div ref="container" /> </template>

要点拆解:

  • container是目标元素引用useParallax的第一个参数target的类型是MaybeElementRef,即可以是 DOM 元素、Vue 组件的 ref,也可以是返回元素的 getter。视差计算以该元素为锚点(鼠标模式下的相对基准)。
  • 返回三个响应式值tilt(俯仰角)、roll(横滚角)与source(当前传感器来源),三者均为ComputedRef,可直接在模板中用于绑定transform
  • 零配置即可运行:不传 options 时,函数会自动探测设备方向支持情况并选择数据源。

下面是一个完整的"视差卡片"示例,把tilt/roll映射为 CSStranslate3d位移:

<script setup lang="ts"> import { useParallax } from '@vueuse/core' const card = ref<HTMLElement | null>(null) const { tilt, roll, source } = useParallax(card) const layerStyle = computed(() => ({ transform: `translate3d(${roll.value * 100}px, ${tilt.value * 100}px, 0)`, })) </script> <template> <div ref="card" class="card"> <div class="card-layer" :style="layerStyle"> 当前传感器: {{ source }} </div> </div> </template>

由于tiltroll已被归一化到-0.5 ~ 0.5区间,将其乘以一个像素系数(如 100)即可得到平滑的位移量,不会出现数值过大或过小的问题。

返回值详解:tilt、roll 与 source

参考文档的类型声明给出了三个返回值的精确定义:

export interface UseParallaxReturn { /** * Roll value. Scaled to `-0.5 ~ 0.5` */ roll: ComputedRef<number> /** * Tilt value. Scaled to `-0.5 ~ 0.5` */ tilt: ComputedRef<number> /** * Sensor source, can be `mouse` or `deviceOrientation` */ source: ComputedRef<"deviceOrientation" | "mouse"> }
返回值类型含义
tiltComputedRef<number>俯仰角视差值,已缩放至-0.5 ~ 0.5(设备前后倾斜 / 鼠标垂直位移)
rollComputedRef<number>横滚角视差值,已缩放至-0.5 ~ 0.5(设备左右倾斜 / 鼠标水平位移)
sourceComputedRef<"deviceOrientation" \| "mouse">当前实际使用的传感器来源,用于调试或 UI 提示(如"请倾斜手机体验")

source的实战价值在于:你可以根据传感器类型切换提示文案或交互暗示。例如在source === 'mouse'时显示"移动鼠标查看效果",在source === 'deviceOrientation'时提示"倾斜设备查看效果",从而在桌面与移动端都获得一致的用户引导。

配置项详解:四个 adjust 回调

参考文档定义了UseParallaxOptions,它继承ConfigurableWindow,并提供四个用于精细调节的调整函数:

export interface UseParallaxOptions extends ConfigurableWindow { deviceOrientationTiltAdjust?: (i: number) => number deviceOrientationRollAdjust?: (i: number) => number mouseTiltAdjust?: (i: number) => number mouseRollAdjust?: (i: number) => number }
配置项作用域作用
deviceOrientationTiltAdjust设备方向模式对设备倾角产生的tilt值做后处理
deviceOrientationRollAdjust设备方向模式对设备倾角产生的roll值做后处理
mouseTiltAdjust鼠标模式对鼠标位移产生的tilt值做后处理
mouseRollAdjust鼠标模式对鼠标位移产生的roll值做后处理

每个adjust函数接收原始计算值i(已归一化到-0.5 ~ 0.5或接近该范围),返回你期望的最终值。常见用途包括:

  • 放大/缩小幅度i => i * 2让某轴位移翻倍;
  • 曲线映射i => i ** 2 * Math.sign(i)保持方向的同时增强边缘手感;
  • 锁定某一轴() => 0关闭该轴上的视差;
  • 反转方向i => -i让层朝相反方向移动,形成深度错位的多层效果。

示例——让设备模式下位移更灵敏、鼠标模式下只保留水平视差:

const { tilt, roll } = useParallax(container, { deviceOrientationTiltAdjust: i => i * 2, deviceOrientationRollAdjust: i => i * 2, mouseTiltAdjust: () => 0, // 桌面端锁死垂直位移 mouseRollAdjust: i => i * 1.5, })

因为四个调整函数可以分别作用于两种模式、两个轴向,所以"桌面端与移动端体验不同"这类需求不需要在业务层写source分支判断,交给 options 即可。

底层原理:useDeviceOrientation 与 useMouse 的自动回退

useParallax本身不直接监听任何 DOM 事件,而是把"数据获取"委托给两个底层组合式函数。要真正理解它的行为,需要分别了解这两个数据源。

数据源一:useDeviceOrientation(设备倾角)

同技能集的 useDeviceOrientation 参考文档 表明,它是对 Web 标准DeviceOrientationEvent的响应式封装,返回四个状态:

状态类型含义
isAbsoluteboolean设备是否提供绝对方向数据
alphanumber绕 z 轴旋转角,0~360 度
betanumber绕 x 轴旋转角,-180~180 度(前后俯仰)
gammanumber绕 y 轴旋转角,-90~90 度(左右横滚)

useParallax正是把beta(前后俯仰)映射到tiltgamma(左右横滚)映射到roll,再通过内部归一化处理缩放到-0.5 ~ 0.5区间,最后交给对应的deviceOrientation*Adjust回调做业务侧微调。

需要说明的是,deviceorientation事件在部分移动平台(如 iOS 13+ 的 Safari)上要求页面运行在 HTTPS 环境,并且需要先通过DeviceOrientationEvent.requestPermission()获得用户授权;在桌面浏览器或未授权的移动浏览器中该事件通常不可用——这正是useParallax引入鼠标回退的动机。从参考文档的实现意图与source返回值的二态设计可以推断useParallax会在初始化时探测设备方向支持情况,不支持或未授权时自动切换为鼠标数据源,这也是source字段存在的根本原因。

数据源二:useMouse(鼠标位置回退)

同技能集的 useMouse 参考文档 显示它是"响应式鼠标位置",返回xysourceType"mouse" | "touch" | null)。关键行为包括:

  • 默认监听touchmove事件(touch选项默认true),移动端触摸也能驱动;
  • type选项支持page/client/screen/movement四种坐标系(默认page),也可传入自定义提取函数;
  • 拖动过程中通过dragover事件持续追踪位置。

在回退模式下,useParallax会把鼠标在目标元素区域内的相对位置换算为-0.5 ~ 0.5的归一化视差值,再经mouse*Adjust回调输出。由于useMouse天然支持触摸事件,手机上的"手指滑动驱动视差"在回退路径下同样可用。

实战落地:在 airi 的 Vue 应用中实现视差层

airi 仓库中所有 Web 形态的应用都通过catalog:引用了@vueuse/core(见 pnpm-workspace.yaml),例如:

  • apps/stage-web:Web 舞台应用,适合做首页角色立绘、装饰层的背景视差;
  • apps/stage-tamagotchi:桌面/Web 养宠应用,可让场景背景随鼠标轻微浮动,增强"容器感";
  • apps/stage-pocket:移动端优先的应用,恰好发挥设备倾角视差的优势;
  • packages/stage-ui 等 UI 包:可把视差层封装为可复用组件。

一个可复用的"多图层视差背景"组件示例(使用<script setup lang="ts">):

<script setup lang="ts"> import { useParallax } from '@vueuse/core' const props = defineProps<{ layers: number // 视差层数 strength?: number // 单层位移强度 }>() const stage = ref<HTMLElement | null>(null) const { tilt, roll, source } = useParallax(stage, { mouseRollAdjust: i => i * 2, mouseTiltAdjust: i => i * 2, }) const layerStyles = computed(() => Array.from({ length: props.layers }, (_, i) => { const depth = (i - (props.layers - 1) / 2) * (props.strength ?? 40) return { transform: `translate3d(${roll.value * depth}px, ${tilt.value * depth}px, 0)`, } }), ) </script> <template> <div ref="stage" class="parallax-stage"> <slot /> <div v-for="(style, i) in layerStyles" :key="i" class="parallax-layer" :style="style" /> </div> </template>

层编号居中者为 0 深度、越靠边缘的层位移越大,从而用translate3d的 z 轴纵深感营造出"多个平面以不同速度移动"的经典视差效果。

若需要"仅当鼠标进入元素后才开始视差"的更精细控制,还可以参考同技能集 Elements 分类下的 useMouseInElement 参考文档:它返回xyisOutside等元素内坐标,可与useParallax组合使用,例如在isOutsidetrue时将视差值平滑归零。

需要如实说明:截至当前仓库代码,useParallax尚未在业务源码中被直接调用(在 apps 与 packages 中未检索到其使用痕迹),但它已被 vueuse-functions 技能集 标记为 AUTO 级别的标准方案,且@vueuse/core依赖在全部 Web 应用中就绪,属于"随时可取用"的现成能力。

使用注意事项与性能建议

  • 移动端权限与 HTTPS:依赖设备倾角时,需在 HTTPS 页面并处理DeviceOrientationEvent.requestPermission()授权流程;未授权时useParallax会自动回退到鼠标/触摸数据源,因此业务代码无需为此报错。
  • SSR 兼容UseParallaxOptions继承ConfigurableWindow,窗口对象可配置化,在 Nuxt / SSR 场景下能安全避免直接访问window
  • 性能tiltrollComputedRef,只会依赖变化时重算;在模板中直接消费即可获得 Vue 的依赖追踪与渲染批处理,无需手动节流。若在adjust回调内做重计算,建议保持纯函数。
  • 无障碍与动效偏好:可以配合prefers-reduced-motion媒体查询,在用户声明"减少动态效果"时关闭视差层,避免强交互动画造成不适。
  • 位移幅度控制:内置的-0.5 ~ 0.5归一化与四个adjust回调是控制手感的标准入口,尽量通过它们调参,而不是在业务层重复处理原始传感器数值。

相关参考文档

  • useParallax 参考文档(本文主体)
  • useDeviceOrientation 参考文档(倾角数据源)
  • useMouse 参考文档(回退数据源)
  • useMouseInElement 参考文档(元素内坐标扩展)
  • vueuse-functions 技能集(组合式函数选型与 Invocation 规则)
  • pnpm-workspace.yaml(仓库级 VueUse 版本目录)

【免费下载链接】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-sama's altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询