除了drag相关的行为和事件,motion中还给开发者提供其他的一些事件,帮助我们更好的完成一些交互行为的开发。

我这里还是重新列一遍和while有关的几个属性,

whileHover

鼠标悬浮时

whileTap

按住时

whileDrag

拖动时

whileFocus

获取焦点时

whileInView

出现在视窗时

这些的使用方式我们已经在动画实现逻辑的内容中讲过,我这里就不赘述了。

黑色圆点为白色方块子元素,尝试点击白色方块中的黑色圆点和非黑色圆点区域

👇

有时候当一个元素拥有pointer(指向型设备或操作)相关的事件绑定,比如dragtap以及相关的while事件,同时,这个元素中还有子元素,当我们操作的是该内部的子元素的时候,我们并不想事件被传递到父元素上,导致父元素触发相应的事件回调,那么我们可以在子元素上设置onPointerDownCapture事件,然后在代码回调中执行e.stopPropagation()

<motion.div whileTap={{ scale: 2 }}>
  <button onPointerDownCapture={e => e.stopPropagation()} />
</motion.div>

#

阻止子元素影响父元素

#

Hover事件

<motion.div onHoverStart={() => console.log('Hover starts')} />

onHoverStart(event, info): void

鼠标悬浮到元素上时触发

event:MouseEvent

info: PanInfo

hover相关的事件,主要用来当一个Pointer设备(比如鼠标)悬浮到元素上或者离开元素时做一些交互处理。与onMouseEnteronMouseLeave不同的是,hover保证只会在实际鼠标事件发生时触发(而不是从触摸输入模拟的浏览器生成的鼠标事件)。

onHoverEnd(event, info): void

鼠标悬浮在元素然后离开时触发

event:MouseEvent

info: PanInfo

<motion.div onHoverEnd={() => console.log("Hover ends")} />

#

Tap事件

tap事件融合了鼠标事件和触摸事件,如果你用鼠标(或者手指按压触摸屏)或者其他的一些设备(比如触控笔),按下某个元素然后释放,完成整个这个过程,就会触发Tap事件。

注意,整个过程要都在元素上才回触发Tap事件,如果按下的时候在元素上,放开的时候已经不在元素范围内了,那么回触发一个tapCancel事件。

如果你按下一个元素是一个可拖拽元素的子元素,那么如果你的按下之后移动超过3个像素的距离,这个元素的tap事件会自动取消执行。

键盘触发tap事件

任何元素如果设置了Tap事件,当这个元素获得焦点了,那么键盘的一些按键是会触发该元素的相关的额Tap事件的

  • 按下回车键(enter)会触发onTapStart事件和whileTap

  • 释放回车键(enter)会触发onTap事件

  • 如果元素在回车键释放前就失去焦点,那么onTapCancel事件会被触发

onTap(event, info): void

在元素上按下并释放然后触发

event:MouseEvent | TouchEvent | PointerEvent

info: TapInfo

包含触发点的坐标信息对象,坐标的信息为x和y

function onTap(event, info) {
  console.log(info.point.x, info.point.y)
}

<motion.div onTap={onTap} />

onTapStart(event, info): void

在元素上按下时触发

event:MouseEvent | TouchEvent | PointerEvent

info: TapInfo

包含触发点的坐标信息对象,坐标的信息为x和y

function onTapStart(event, info) {
  console.log(info.point.x, info.point.y)
}

<motion.div onTapStart={onTapStart} />

onTapCanel(event, info): void

在元素上按下并不在元素上释放时触发

event:MouseEvent | TouchEvent | PointerEvent

info: TapInfo

包含触发点的坐标信息对象,坐标的信息为x和y

function onTapCancel(event, info) {
  console.log(info.point.x, info.point.y)
}

<motion.div onTapCancel={onTapCancel} />

#

Pan事件

pan事件是设备(鼠标)或者手指按住一个元素,然后不放开,接着移动超过3个像素的距离,就会触发,当设备等放开后,pan事件才结束。

drag事件其实就是基于pan事件的实现的。

onPan(event, info): void

在元素上按下并在元素上移动超过3像素

注意,一直移动会一直触发

如果在移动端使用pan事件,要注意要限制元素的滚动方向(x/y轴),或者直接用css的touch-action属性把元素设置成任意方向都不会滚动

event:MouseEvent | TouchEvent | PointerEvent

info: PanInfo

PanInfo

这个对象有这些数据信息,这个信息都有x和y的值

point: 事件触发点的坐标值

delta: 和上一次触发点的距离

offset: 和一开始触发点的相比的偏移量

velocity: 当前触发点的速度值

function onPan(event, info) {
  console.log(info.point.x, info.point.y)
}

<motion.div onPan={onPan} />

onPanStart(event, info): void

在元素上按下并在元素上移动超过3像素时

只触发一次

event:MouseEvent | TouchEvent | PointerEvent

info: PanInfo

同onPan事件中的PanInfo

onPanEnd(event, info): void

pan行为结束时触发

只触发一次

event:MouseEvent | TouchEvent | PointerEvent

info: PanInfo

同onPan事件中的PanInfo

function onPanStart(event, info) {
  console.log(info.point.x, info.point.y)
}

<motion.div onPanStart={onPanStart} />
function onPanEnd(event, info) {
  console.log(info.point.x, info.point.y)
}

<motion.div onPanEnd={onPanEnd} />

#

Animation事件

onUpdate(latest): void

事件每帧最多执行一次,回调参数返回的是最新的 motion value 的值

latest: ResolvedValues

function onUpdate(latest) {
  console.log(latest.x, latest.opacity)
}

<motion.div animate={{ x: 100, opacity: 0 }} onUpdate={onUpdate} />