使用IntersectionObserver添加过度效果

194 阅读1分钟

先看效果

msedge_jbTlF1FFuW.gif

代码

<template>
  <main class="w-full h-full p-5 overflow-x-hidden">
    <ScrollBox animate="zoomIn">
      <template #default="{ useRandomBg }">
        <div class="p-10 h-[200px] my-2 cursor-pointer" v-for="item in 100" :key="item" :style="useRandomBg()">
          box{{ item }}
        </div>
      </template>
    </ScrollBox>
  </main>
</template>
<script lang="ts" setup></script>
<style lang="scss" scoped></style>

ScrollBox组件

<template>
  <div ref="mainRef" class="w-full h-full">
    <slot :useRandomBg="useRandomBg"></slot>
  </div>
</template>
<script lang="ts" setup>
import { useRandomBg } from '@/hooks/useRandomBg'

const props = withDefaults(
  defineProps<{
    /**
     * 过度动画名称
     * default ==> fadeInRight
     * 参考 https://animate.style/
     */
    animate?: string

    /**过渡时间 default ==> 0.5s */
    delay?: string
  }>(),
  {
    animate: 'fadeInRight',
    delay: '0.5s',
  },
)

const mainRef = ref()
let observer: IntersectionObserver
onMounted(() => {
  Array.from(mainRef.value.children as NodeListOf<Element>).map((e) => {
    observer = new IntersectionObserver((entries) => {
      // 可见性变化处理
      entries.forEach((entry) => {
        /** 元素可见*/
        if (entry.isIntersecting) {
          e.classList.add('animate__animated')
          e.classList.add('animate__' + props.animate)
          e.classList.add('animate__delay-' + props.delay)
        } else {
          // e.classList.remove('animate__animated')
          // e.classList.remove('animate__' + props.animate)
          // e.classList.remove('animate__delay-' + props.delay)
          // console.log(`元素不可见 ==>`)
        }
      })
    })
    observer.observe(e)
  })
})

onUnmounted(() => (observer = null))
</script>
<style lang="scss"></style>

组件使用animate.css实现过度效果 需要引入

pnpm i animate.css
import 'animate.css'

需要想要的效果直接去animate.css官网 复制类名就可以直接使用了

<ScrollBox animate="zoomIn">
...
</ScrollBox>