当前位置: 首页 > news >正文

vue3使用插件封装指令实现页面滚动动画

效果展示:

vue封装插件需要使用到install函数

export default ScrollAnimationPlugin = {
    install(app: App, options = {}) {
        // 需要实现的内容
    }
}

vue指令语法:

    app.directive('scroll-animation', {
      mounted(el: HTMLDivElement, binding: any) {
        // 需要实现的内容

      }
    })

监听页面滚动的web-api: IntersectionObserver

创建一个新的 IntersectionObserver 对象,当其监听到目标元素的可见部分(的比例)超过了一个或多个阈值(threshold)时,会执行指定的回调函数。

它接受2个参数,第一个是callback:回调函数,第二个是options:配置项

语法:

var observer = new IntersectionObserver(callback[, options]);

参考:IntersectionObserver文档

结合以上内容实现如下:

// scrollAnimation.ts
import { type App, nextTick } from 'vue'

const ScrollAnimationPlugin = {
  install(app: App, options = {}) {
    // 合并默认配置
    const defaultConfig = {
      defaultDistance: '100px',
      defaultDuration: 0.6,
      defaultDelay: 0,
      defaultClass: 'animate-from-bottom'
    }

    const config = { ...defaultConfig, ...options }

    app.directive('scroll-animation', {
      mounted(el: HTMLDivElement, binding: any) {
        const customConfig = binding.value || {}
        const delay = customConfig.delay ?? config.defaultDelay
        const distance = customConfig.distance ?? config.defaultDistance
        const duration = customConfig.duration ?? config.defaultDuration
        const animationClass = customConfig.class ?? config.defaultClass

        // 设置初始样式
        el.style.opacity = '0'
        el.style.transform = `translateY(${distance})`
        el.style.transition = `all ${duration}s ease-out ${delay}ms`

        const observer = new IntersectionObserver(
          entries => {
            entries.forEach(entry => {
              if (entry.isIntersecting) {
                nextTick(() => {
                  el.classList.add(animationClass, 'active')
                  observer.unobserve(el)
                }).then()
              }
            })
          },
          { threshold: 0.1 }
        )

        observer.observe(el)
      }
    })
  }
}

export { ScrollAnimationPlugin }

CSS样式文件:

/* animations.css */

/* 基础动画样式 */

.animate-from-bottom.active {
  opacity: 1 !important;
  transform: translateY(0) !important;
}

.animate-from-left.active {
  opacity: 1 !important;
  transform: translateX(0) !important;
}

.animate-fade.active {
  opacity: 1 !important;
  transform: none !important;
}

/* 性能优化 */
[data-scroll-animation] {
  will-change: transform, opacity;
}

main.ts 引入使用:

// main.ts

import { ScrollAnimationPlugin } form './scrollAnimation.ts'

import App from './App.vue'

const app = createApp(App)

app.use(ScrollAnimationPlugin)

app.mount('#app')
// useComponent.vue

<template>
    <!-- 在你需要动画的元素上使用指令 -->
    <div v-scroll-animation>

    </div>
</template>

相关文章:

  • 鸿蒙NEXT开发-元服务和服务卡片的开发
  • ES6 特性全面解析与应用实践
  • HTTP 请求时传递多部分表单数据
  • axios请求设置request umijopenai生产前端请求 ts状态全局 v-if v-else 与动态js变量
  • C#中的字典怎么使用?
  • Linux10-共享队列
  • android智能指针android::sp使用介绍
  • 工程化与框架系列(4)--Webpack 高级配置详解
  • 从ETL到数仓分层:大数据处理的“金字塔”构建之道
  • 【MATLAB例程】三维下的IMM(交互式多模型),模型使用CV(匀速)和CA(匀加速)
  • Vue程序下载
  • 大白话TypeScript第七章TypeScript 与不同技术栈的深度融合及拓展应用
  • 【Cadence仿真学习笔记】ADS Dynamic Link报错model is reserved的解决办法
  • vue3在使用ts为模板引用标注类型时,vue3.5+版本有了全新写法
  • conda怎么迁移之前下载的环境包,把python从3.9升级到3.10
  • 非关系型数据库和关系型数据库的区别
  • 2025年度福建省职业院校技能大赛高职组“信息安全管理与评估”赛项规程样题模块二
  • Nginx系列06(Nginx 缓存配置、SSL/TLS 配置)
  • DeepSeek + 自由职业 发现新大陆,从 0 到 1 全流程跑通商业 IP
  • UE5 Slate类的基础创建
  • 做印刷在哪个网站接单好好/搜索引擎优化的意思
  • 做网站多少钱赚钱吗/建站是什么意思
  • 好点的Wordpress主题/排名怎么优化快
  • 做进料加工在哪个网站上做/网推app怎么推广
  • 一个seo良好的网站其主要流量往往来自/聚合搜索引擎
  • 网站建设需求计划书/百度首页清爽版