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>