vue2自定义指令实现滚动动画-使用IntersectionObserver观察器
vue2自定义指令实现滚动动画
使用IntersectionObserver观察器
效果(滑动后触发动画):
ScrollAnimation.vue代码:
<template>
<div>
<div class='list'>
<div v-slide-in
class='item'
v-for='item in 100'
:key='item'
:style="{background:randomColor()}">{{item}}</div>
</div>
</div>
</template>
<script>
const elMap = new WeakMap()
const ob = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
elMap.get(entry.target).play()
ob.unobserve(entry.target)
}
})
})
export default {
name: 'ScrollAnimation',
methods: {
randomColor() {
return `rgb(${Math.floor(Math.random()*255)},${Math.floor(Math.random()*255)},${Math.floor(Math.random()*255)})`
},
},
directives: {
'slide-in': {
inserted(el) {
const rect = el.getBoundingClientRect()
if (!(rect.top > window.innerHeight)) {
return
}
const an = el.animate([{
transform: 'translateY(50px)',
opacity: 0.5
},
{
transform: 'translateY(0px)',
opacity: 1
}
], {
duration: 1000,
easing: 'ease-out',
fill: 'forwards'
})
elMap.set(el, an)
an.pause()
ob.observe(el)
},
unbind(el) {
ob.unobserve(el)
}
}
},
}
</script>
<style scoped>
* {
margin: 0;
padding: 0;
}
.list {
width: 90%;
margin: 0 auto;
}
.item {
width: 100%;
height: 100px;
margin-bottom: 10px;
display: flex;
justify-content: center;
align-items: center;
font-size: 30px;
font-weight: bold;
color: #fff;
border-radius: 10px;
}
</style>