vue之使用IntersectionObserver API实现封装滚动动画组件

IntersectionObserver API 是浏览器监听元素是否在可视区域的API,详情见:vue自定义指令之图片懒加载

使用:

className 自定义动画类名
mode shutdown表示执行一次,noShoudown 表示执行多次,持续监听

<Scroll className="ani">
	<div>
          我是内我是内容我是内容我是内容我是内容容我是内我是内容我是内容我是内容我是内容容我是内我是内容我是内容我是内容我是内容容我是内我是内容我是内容我是内容我是内容容我是内我是内容我是内容我是内容我是内容容我是内我是内容我是内容我是内容我是内容容
	</div>
</Scroll>

组件

<template>
  <div
    ref="scrollRef"
    class="scroll"
    :class="[
      isRunning && !!className
        ? className
        : isRunning && !className
        ? 'onscroll'
        : '',
    ]"
  >
    <slot></slot>
  </div>
</template>

<script>
export default {
  props: {
    className: {
      type: String,
      default: '',
    },
    mode: {
      type: String,
      default: 'shutdown',
    },
  },
  data() {
    return {
      isRunning: false,
    }
  },
  mounted() {
    this.handelScroll()
  },
  methods: {
    handelScroll() {
      const el = this.$refs.scrollRef
      const observer = new IntersectionObserver(
        ([{ isIntersecting }]) => {
          if (this.mode === 'noShutdown') {
            this.isRunning = !!isIntersecting
          } else if (isIntersecting) {
            this.isRunning = true
            // 关闭监听
            observer.unobserve(el)
          }
          el.onerror = (err) => console.error(err)
        },
        { threshold: 0 }
      )
      //   开启监听
      observer.observe(el)
    },
  },
}
</script>

<style lang="scss" scoped>
// 动画
@keyframes scroll-ani {
  0% {
    opacity: 0;
    transform: translate3d(0, 100%, 0);
  }
  100% {
    opacity: 1;
    transform: translateZ(0);
  }
}

.onscroll {
  animation-duration: 0.46s;
  animation-delay: 0.2s;
  animation-fill-mode: both;
  animation-timing-function: ease-in-out;
  animation-name: scroll-ani;
  opacity: 0;
}
</style>
之前方法

通过计算元素偏移量与视口高度距离得出是否在可视区域

<script>
export default {
  data: () => {
    return {
      running: false,
      screenHeight: 0,
      currentScroll: 0,
      tranTop: 0,
    }
  },
  mounted() {
    this.init()
    window.addEventListener('scroll', this.handleScroll, true)
  },
  beforeDestroy() {
    window.removeEventListener('scroll', this.handleScroll, true)
  },
  methods: {
    init() {
      this.screenHeight = window.innerHeight
      this.tranTop =
        this.$refs.scrollRef.getBoundingClientRect().top + window.scrollY
    },
    // 滚动动画
    handleScroll() {
      this.currentScroll = window.pageYOffset
      if (this.currentScroll >= this.tranTop - this.screenHeight) {
        this.running = true
      } else {
        this.running = false
      }
    },
  },
}
</script>
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Vue 3 中可以使用 Intersection Observer API实现懒加载。Intersection Observer API 可以观察一个元素是否进入了视口(viewport)或者离开了视口。 首先,你需要创建一个指令来实现懒加载: ```javascript const lazyLoad = { mounted(el, binding) { let options = { rootMargin: '0px', threshold: 0.1 }; const observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { binding.value(); observer.unobserve(el); } }); }, options); observer.observe(el); } } export default lazyLoad; ``` 在这个指令中,我们使用Intersection Observer API 来观察元素是否进入了视口。当元素进入视口时,我们会调用指令传入的回调函数。 接下来,在组件使用这个指令: ```html <template> <div class="container"> <img v-lazyload="loadImage" :data-src="imageUrl" /> </div> </template> <script> import lazyLoad from "@/directives/lazyLoad"; export default { directives: { lazyload: lazyLoad }, data() { return { imageUrl: "https://example.com/image.jpg" }; }, methods: { loadImage() { const img = new Image(); img.onload = () => { this.$el.setAttribute("src", this.imageUrl); this.$el.removeAttribute("data-src"); }; img.src = this.imageUrl; } } }; </script> ``` 在这个例子中,我们在图片上使用指令 `v-lazyload`,并且传入了一个回调函数 `loadImage`。当图片进入视口时,指令会调用 `loadImage` 函数来加载图片。 在 `loadImage` 函数中,我们创建一个新的 `Image` 对象,并设置其 `onload` 回调函数。当图片加载完成时,我们将图片的 `src` 属性设置为 `imageUrl`,并移除 `data-src` 属性,以此来显示图片。 希望这个例子可以帮助你实现 Vue 3 中的懒加载。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凡小多

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值