前端开发攻略---Vue通过自定义指令实现元素平滑上升的动画效果(可以自定义动画时间、动画效果、动画速度等等)。

1、演示

2、介绍

这个指令不是原生自带的,需要手动去书写,但是这辈子只需要编写这一次就好了,后边可以反复利用。

3、关键API

IntersectionObserver

IntersectionObserver 是一个用于监测元素是否进入或离开视口(viewport)的 API。它可以帮助你在页面滚动时或者元素位置改变时进行回调操作,这样你就可以根据元素是否可见来触发动作或者动画效果。

使用 IntersectionObserver 的基本步骤如下:

  1. 创建一个 IntersectionObserver 对象,并指定一个回调函数。这个回调函数会在被观察的元素进入或离开视口时被调用。

  2. 使用 observe() 方法开始观察指定的元素。你可以同时观察多个元素。

  3. 在回调函数中处理元素的可见状态变化。根据元素的可见性状态来执行相应的操作,比如触发动画、加载内容等。

  4. 在不需要观察元素时,使用 unobserve() 方法停止观察。

以下是一个简单的示例代码,演示了如何使用 IntersectionObserver 来监测元素的可见性:

javascript 复制代码
// 创建一个 IntersectionObserver 对象
const observer = new IntersectionObserver((entries) => {
  // 遍历观察到的所有元素
  entries.forEach(entry => {
    // 如果当前元素进入视口
    if (entry.isIntersecting) {
      // 执行相应的操作,比如触发动画
      entry.target.classList.add('animate');
      // 停止观察当前元素,可根据需求决定是否停止观察
      observer.unobserve(entry.target);
    }
  });
});

// 要观察的目标元素
const targetElement = document.querySelector('.target');

// 开始观察目标元素
observer.observe(targetElement);

4、Vue文件代码

html 复制代码
<template>
  <div class="container">
    <div v-slide-in class="item" v-for="item in 10">{{ item }}</div>
  </div>
</template>

<script setup>
import { ref, reactive } from 'vue'
</script>

<style scoped lang="scss">
.container {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.item {
  width: 50%;
  height: 200px;
  margin-bottom: 20px;
  text-align: center;
  line-height: 200px;
  font-size: 50px;
  color: #fff;
  box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 10px 0px;
}
.item:nth-child(1) {
  background-color: rgb(87, 139, 19);
}
.item:nth-child(2) {
  background-color: rgb(33, 139, 19);
}
.item:nth-child(3) {
  background-color: rgb(139, 19, 35);
}
.item:nth-child(4) {
  background-color: rgb(139, 19, 87);
}
.item:nth-child(5) {
  background-color: rgb(139, 19, 135);
}
.item:nth-child(6) {
  background-color: rgb(91, 19, 139);
}
.item:nth-child(7) {
  background-color: rgb(19, 133, 139);
}
.item:nth-child(8) {
  background-color: rgb(221, 218, 40);
}
.item:nth-child(9) {
  background-color: rgb(173, 139, 115);
}
.item:nth-child(10) {
  background-color: rgb(29, 28, 27);
}
</style>

5、指令文件及代码注释(清晰明了)

javascript 复制代码
// WeakMap是一种键值对的集合
// 这里用来将一个dom元素和一种动画对应起来
const map = new WeakMap()

// 创建一个观察对象
const ob = new IntersectionObserver(entries => {
  // 遍历所有被观察的元素 entries为一个数组
  for (const entry of entries) {
    // 判断该元素是否与视口相交(出现在视口里面了)
    if (entry.isIntersecting) {
      // 判断目标元素是出现在上视口还是下视口
      if (entry.boundingClientRect.top > entry.rootBounds.top) {
        // 找出这个元素对应的动画
        const animation = map.get(entry.target)
        if (animation) {
          // 播放该元素的动画
          animation.play()
        }
      }
    }
  }
})
// 辅助函数,用来判断页面上的元素是否在视口外
function isBelowViewport(el) {
  const rect = el.getBoundingClientRect()
  return rect.top > window.innerHeight
}

export default function (app) {
  app.directive('slideIn', {
    mounted(el, bindings) {
      // 如果元素已经在视口内了,直接return 不加动画
      if (!isBelowViewport(el)) return
      //  创建一个动画  animate是Vue自带的
      const animation = el.animate(
        [
          // 数组的每一个对象都表示关键帧 相当于css中的 @keyframes 这里想写多少个就写多少个
          {
            transform: `translateY(${200}px)`,
          },
          {
            transform: `translateY(0px)`,
          },
        ],
        // duration:执行时间  easing:动画效果,fill:动画结束过后的行为  这些跟css中的一样
        { duration: 1000, easing: 'ease-in-out', fill: 'forwards' }
      )
      // 一开始的时候让动画暂停,这里只是先定义好
      animation.pause()
      // 当元素进入视口的时候在进行动画播放
      ob.observe(el)
      // 存储键值
      map.set(el, animation)
    },
    // 在元素卸载时,取消观察
    unmounted(el) {
      ob.unobserve(el)
    },
  })
}
相关推荐
半青年8 分钟前
Qt图表库推荐指南与分析
c语言·开发语言·javascript·c++·qt·信息可视化
Yvonne爱编码12 分钟前
CSS- 4.3 绝对定位(position: absolute)&学校官网导航栏实例
前端·css·html·html5·hbuilder
繁依Fanyi1 小时前
ImgShrink:摄影暗房里的在线图片压缩工具开发记
开发语言·前端·codebuddy首席试玩官
卓律涤1 小时前
【找工作系列①】【大四毕业】【复习】巩固JavaScript,了解ES6。
开发语言·前端·javascript·笔记·程序人生·职场和发展·es6
Ten peaches2 小时前
Selenium-Java版(环境安装)
java·前端·selenium·自动化
Enti7c2 小时前
BOM知识点
javascript
心.c2 小时前
vue3大事件项目
前端·javascript·vue.js
姜 萌@cnblogs2 小时前
【实战】深入浅出 Rust 并发:RwLock 与 Mutex 在 Tauri 项目中的实践
前端·ai·rust·tauri
蓝天白云下遛狗2 小时前
google-Chrome常用插件
前端·chrome
多多*3 小时前
Spring之Bean的初始化 Bean的生命周期 全站式解析
java·开发语言·前端·数据库·后端·spring·servlet