跳过主要内容

在 v3.10.0 中新增

Observer

快速入门

CDN 链接

gsap.registerPlugin(Observer) 

最简用法

Observer.create({
target: window, // can be any element (selector text is fine)
type: "wheel,touch", // comma-delimited list of what to listen for
onUp: () => previous(),
onDown: () => next(),
});

一种超级灵活、统一的方式来感知所有(触摸/鼠标/指针)设备上的有意义事件,而无需纠结于各种实现细节。也许您希望响应“类似滚动”的用户行为,这可能是一个鼠标滚轮旋转、手指在触摸设备上滑动、拖动滚动条,或指针按下并拖动……当然您需要方向数据和速度信息。没问题!

详细操作指南

告诉 Observer 要监听哪些事件类型(wheel、touch、pointer 和/或 scroll),它将在每个 requestAnimationFrame tick 期间收集 delta 值(默认情况下为了性能会进行防抖处理),并自动确定最大的 delta,然后触发相应的回调函数,如等等(详见下面的完整列表)。防抖处理。由于 ScrollTrigger 的onUp, onDown, onDrag,等等(见下文完整列表)。

看看基于用户向上/向下滑动或使用鼠标滚轮时触发 next()/previous() 函数有多么简单:

Observer.create({
target: window, // can be any element (selector text is fine)
type: "wheel,touch", // comma-delimited list of what to listen for ("wheel,touch,scroll,pointer")
onUp: () => previous(),
onDown: () => next(),
});
信息

Observer 也包含在 ScrollTrigger 中!

这里还有一个ScrollTrigger.observe()方法,其作用与Observer.create()完全相同。由于 ScrollTrigger 的normalizeScroll()功能在底层使用了 Observer(因此它已经包含在 ScrollTrigger 中),公开它的功能是有意义的,这样如果您已经在项目中使用了 ScrollTrigger,就可以避免将 Observer 作为单独的文件加载。不客气。🙂

演示

注意下面的演示中实际上没有滚动,但您可以使用鼠标滚轮(或者在触摸设备上滑动)来启动移动,使其“感觉”像在滚动:

加载中...

特性亮点
  • 丰富的回调系统包括 onDown、onUp、onLeft、onRight、onDrag、onDragStart、onDragEnd、onHover、onHoverEnd、onToggleY、onToggleX、onChangeX、onChangeY、onChange、onClick、onPress、onRelease、onMove、onWheel 以及 onStop
  • 默认情况下为了最佳性能进行了防抖处理(你可以设置 by default for maximum performance (you can set debounce: false如果需要的话)
  • 跨浏览器兼容— 自动判断应使用 TouchEvents、PointerEvents 还是 MouseEvents。
  • 自动优先选择具有最大delta 的事件(例如,在同一个防抖时间段内同时发生了 wheel、scroll 和 touch 事件)
阅读更多...
  • 忽略某些元素,比如ignore: ".deadzone"
  • 获取速度(分别在 x 轴和 y 轴方向)以及 clientX 和 clientY 坐标(用于 touch/pointer 事件)
  • 设置一个拖拽的最小阈值. For example, dragMinimum: 5 would only fire the onDragStart/onDrag/onDragEnd callbacks if the user moved 5 pixels or more.
  • 设置一个tolerance,以便仅当达到最小 delta 时才触发运动相关回调。例如,tolerance: 50 表示只有当变化至少为 50 像素时才开始触发回调,一旦达到该值后重新开始计数。tolerance: 50 would wait until there has been a change of at least 50 pixels, and then once that's reached it starts over.
  • 设置一个wheelSpeed乘数因子,如果你希望调整 wheel 相关的 delta 值(加快或减慢)。
  • 与 GSAP 集成,并且ScrollTrigger
  • 大约压缩后 3.5KB

配置对象

传递给Observer.create()的配置对象可以包含以下任意可选属性:

    属性

    描述

  • axis

    字符串— 当lockAxis: true被设置时,每次按压后的首次拖拽动作(类型为 "pointer" 和/或 "touch")将根据用户移动的方向设置axis属性为 "x" 或 "y"。你可以使用onLockAxis()回调来知道何时被设置。
  • capture

    Boolean- 如果设置为true,这会让 touch/pointer 相关的监听器使用捕获阶段。类似于执行 addEventListener("[type]", func, {capture: true});
  • debounce

    Boolean— 默认情况下,Observer 会对事件进行防抖处理,以便在每个 requestAnimationFrame() tick 期间累积 delta 值以提高性能,但你可以通过debounce: false来禁用该项功能。在这种情况下,它会在每个事件上立即检查。防抖会影响除onPress, onRelease, onHover, onHoverEnd, onClick, onDragStart,以及onDragEnd之外的所有回调,因为这些回调与 delta 无关。
  • dragMinimum

    数字— 被视为“拖拽”所需的最小距离(以像素为单位)。这有助于防止特别是在触摸设备上微小动作被误认为有明确意图。例如,仅用手指按下手机屏幕可能会注册出几个像素的轻微移动,尽管用户认为自己的手指是静止的。dragMinimum 仅适用于按下后的初始移动,之后继续拖拽只会受到 "tolerance" 的节流控制。
  • id

    字符串— 一个任意字符串 ID,可通过Observer.getById().
  • ignore

    元素 | 字符串 | 数组— 你希望 observer忽略的元素,当这些元素触发了一个 scroll/touch/pointer/mouse 事件时,整个事件将被完全忽略。它会检查事件的目标来决定是否忽略。你可以将event.target定义为一个 Element 引用、类似ignore的选择器文本,或者一个元素数组(数量不限)。".ignore-me", or an Array of elements (it can be as many as you'd like).
  • lockAxis

    Boolean- 如果设置为true,Observer 将会在每次按压后首次拖拽移动时(类型为 "pointer" 和/或 "touch")检测方向,并锁定到该方向直到用户释放指针/触摸。因此,如果首次拖拽是水平方向,则只会有像onChangeX()这样与水平相关的回调被触发直到指针/触摸释放。甚至还有一个onLockAxis()回调供你绑定。
  • onChange

    函数— 当在任一y轴(垂直方向)或者x轴(水平方向)检测到移动时调用的函数。只要移动持续就会不断调用该函数(受任何 tolerance 阈值限制)。
  • onChangeX

    函数— 当在 x 轴(水平方向)检测到移动时调用的函数。只要移动持续就会不断调用该函数(受任何 tolerance 阈值限制)。
  • onChangeY

    函数— 当在 y 轴(垂直方向)检测到移动时调用的函数。只要移动持续就会不断调用该函数(受任何 tolerance 阈值限制)。
  • onClick

    函数— 当目标被点击时调用的函数。
  • onDown

    函数— 当检测到向下的运动时调用的函数,这意味着 delta 值增加(比如你的手指/鼠标向下拖动…使得y坐标增加)。如果你想仅反转鼠标滚轮的 delta,你可以设置wheelSpeed: -1因为它是一个乘数。
  • onDragStart

    函数— 当用户按下目标并开始拖动时调用的函数(受dragMinimum限制)。这只适用于 "touch" 和/或 "pointer" 类型。
  • onDrag

    函数- 用户移动指针/触摸/鼠标时调用的函数在按下时在目标元素上(仅适用于"touch"和/或"pointer"类型)。
  • onDragEnd

    函数- 用户停止在目标元素上拖动时调用的函数(仅适用于"touch"和/或"pointer"类型)。
  • onLeft

    函数- 检测到向左方向移动时调用的函数。
  • onLockAxis

    函数- 当轴锁定时调用的函数(需要lockAxis: true)。可以通过观察器的axis属性("x"或"y")检查是哪个轴。
  • onHover

    函数- 指针/鼠标悬停在目标上时调用的函数("pointerenter"/"mouseenter"事件)。
  • onHoverEnd

    函数- 指针/鼠标移出目标时调用的函数("pointerleave"/"mouseleave"事件)。
  • onMove

    函数- 用户在悬停于目标元素上时移动指针/鼠标时调用的函数(仅适用于"pointer"类型)。它内部监听"pointermove"/"mousemove"事件。如果您希望只在按下并拖动时触发,请使用onDrag如果您想让它仅在按压和拖动时触发。需要注意的是,当您定义onMove时,它会导致观察者在悬停期间测量delta值悬停期间在目标上方,从而触发适当的与移动相关的回调函数,如onUp、onDown、onChange等,以响应在目标上方的任何指针/鼠标移动。通常情况下,与移动相关的回调函数只有在用户按下并拖动时才会被触发.
  • onPress

    函数- 用户按下目标元素时调用的函数(仅适用于"touch"和/或"pointer"类型)。
  • onRelease

    函数- 调用onPress后释放触摸/指针时调用的函数(仅适用于"touch"和/或"pointer"类型)。
  • onRight

    函数- 检测到向右方向移动时调用的函数。
  • onStop

    函数- 当变化停止至少0.25秒时调用的函数(可通过onStopDelay)
  • onStopDelay

    数字- 变化停止后等待多少秒才调用onStop的时间(默认:0.25秒)。
  • onToggleX

    函数- 移动切换方向时调用的函数在x轴上(水平方向)。
  • onToggleY

    函数- 移动切换方向时调用的函数在y轴上(垂直方向)。
  • onUp

    函数- 检测到向上运动时调用的函数,意味着delta值减少(比如手指/鼠标向上滑动...这使得y坐标减少)。如果您只想反转鼠标滚轮delta值,可以设置wheelSpeed: -1因为它是一个乘数。
  • onWheel

    函数- 鼠标滚轮使用时调用的函数。
  • scrollSpeed

    数字- 滚动delta值的乘数。这仅适用于"scroll"类型,意思是当目标分派一个不同于滚轮事件的滚动事件时。您可以设置scrollSpeed: -1来反转delta值,并使其调用onUp而不是onDown(反之亦然)。scrollSpeed: 0.5将使delta值变为一半通常情况下的数值。注意:还有一个单独的wheelSpeed选项,仅适用于滚轮事件。
  • 目标对象

    元素 | 字符串- 应该监听事件的元素。默认情况下,它是主视口。
  • tolerance

    数字- 触发其中一个回调(如onUp, onDown, onChangeY等)所需的最小距离(以像素为单位)。例如,如果容差是10但用户只移动了8个像素,则不会触发回调。一旦距离超过容差量,就会触发回调并重置,再次等待该距离被超过之后才会再次触发回调。
  • type

    字符串- 包含您想要监听的动作类型的逗号分隔列表,可以包含以下内容中的任意一个(或全部):"wheel,touch,scroll,pointer"。 "touch"适用于任何触控设备,无论浏览器如何(iOS/Android可能在底层使用TouchEvent,而微软可能使用PointerEvent,但Observer将它们都包括在"touch"中)。 "pointer"涵盖所有非触控的指针/鼠标按下/拖动/滑动动作。"wheel"用于鼠标滚轮移动,"scroll"用于滚动事件。默认是 "wheel,touch,pointer"
  • wheelSpeed

    数字- 滚轮delta值的乘数。默认情况下,它只是传递浏览器报告的滚轮事件delta值,但可能看起来比使用指针按下/拖动时更快/更慢,您需要一种方法使它们更相似。例如,为了使滚轮delta值变成正常值的一半,您可以设置wheelSpeed: 0.5。您可以设置wheelSpeed: -1来反转delta值,并使其调用onUp而不是onDown(反之亦然)。注意:还有一个单独的scrollSpeed选项,仅适用于滚动事件。

回调数据

每个回调都会接收到观察者实例本身作为唯一的参数,以便您可以轻松访问诸如self.velocityX, self.velocityY, self.deltaX, self.deltaY, self.x, self.y等数据(请参阅左侧边栏了解所有可用属性的列表),例如:

Observer.create({
...
onChange: (self) => {
console.log("velocity:", self.velocityX, self.velocityY, "delta:", self.deltaX, self.deltaY, "target element:", self.target, "last event:", self.event);
}
});

导航栏左侧有属性列表。

展示及教程演示

属性

deltaX: 数值

自上次在此轴上触发回调以来的水平变化量(以像素为单位)。例如,onChangeX或者onRight

deltaY: 数值

自上次在此轴上触发回调以来的垂直变化量(以像素为单位)。例如,onChangeY或者onDown

event: 事件

最近的事件对象(可能是TouchEvent、PointerEvent、MouseEvent、WheelEvent或ScrollEvent,具体取决于您定义的type类型)

isDragging:布尔值

当用户按下target并且拖动距离超过dragMinimum(默认为0)时为真,直到释放触摸/指针为止(即使用户继续在目标范围外拖动isDragging设置为true until the touch/pointer is released (even if the user continues dragging 也是如此))。

isEnabled:布尔值

指示观察者是否启用。使用enable()disable()设置状态的方法。当观察者被禁用时,它会从目标上移除其所有事件监听器,并且显然不会触发任何回调。onEnableonDisable回调函数,当你启用或禁用观察者时当然会被调用。

isPressed:布尔值

设为true当用户按住目标时(仅适用于type"pointer" 和 "touch" 类型)

startX: 数值

这个clientX来自最近一次的onPresstouch/pointer 事件,表示相对于视口左侧边缘的水平距离。只有当你将type设置为包含 "touch" 和/或 "pointer" 时才会更新。这对于拖动逻辑非常有用。

startY: 数值

这个clientY来自最近一次的onPresstouch/pointer 事件,表示相对于视口顶部边缘的垂直距离。只有当你将type设置为包含 "touch" 和/或 "pointer" 时才会更新。这对于拖动逻辑非常有用。

Observer.isTouch: 数值

一种区分当前设备触控能力的方式 —0表示仅支持鼠标/指针操作(无触控),1表示仅支持触控,2表示同时支持两者。

目标对象: Element

目标元素

vars: 对象

最初传递给 Observer.create() 的配置对象。

velocityX: 数值

水平速度(单位为像素每秒)。

velocityY: 数值

垂直速度(单位为像素每秒)。

x: 数值

垂直位置clientX来自最近一次 touch/pointer 事件,表示相对于视口左侧边缘的水平距离。只有当你将type设置为包含 "touch" 和/或 "pointer" 时才会更新。

y: 数值

垂直位置clientY来自最近一次 touch/pointer 事件,表示相对于视口顶部边缘的垂直距离。只有当你将type设置为包含 "touch" 和/或 "pointer" 时才会更新。

方法

disable( ) : void

禁用观察者,移除必要的事件监听器,并在观察者尚未禁用的情况下触发onDisable回调函数。

enable( event:Event ) : Self

启用观察者,添加必要的事件监听器,并在观察者尚未启用的情况下触发onEnable回调函数。

kill( ) : void

销毁观察者实例,调用disable()并将其从内部数组中移除,使其无法再通过 .getAll() 或 .getById() 被找到,从而可以被垃圾回收。这是永久性的操作。如果你计划稍后再次启用该实例,请使用disable()而不是kill().

Observer.create( vars:Object ) : Observer

根据提供的配置详细信息创建一个新的 Observer 实例。

Observer.getAll( ) : 数组

获取所有已创建(并且未销毁)的观察者数组。例如,如果您的框架要求您在路由更改时销毁所有内容,则此方法可能会很有用。

Observer.getById( id:String ) : Observer

具有匹配id的观察者实例,该 ID 在配置中定义。vars(如果没有找到匹配的 ScrollTriggers,则返回 undefined)

常见问题

可以将多个 Observer 实例应用到同一个目标吗?

当然可以!例如,当您希望某些回调去抖动而其他不进行去抖动时,这将很有用。请记住,您可以随时 .disable() 和 .enable() 观察者。

如果我已经加载了 ScrollTrigger,是否还需要额外加载 Observer?

不需要,Observer 已经包含在 ScrollTrigger 文件中;你可以通过ScrollTrigger.observe()访问它并跳过单独加载 Observer 文件。

示例演示

查看完整系列的使用演示和我们最喜欢的社区灵感演示在 CodePen 上。

无噪 Logo
无噪文档
中文文档 · 复刻官网
查看所有 ↗