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>