自定义指令 下拉平滑过度
2024-03-14 本文已影响0人
抽疯的稻草绳
<template>
<div class="container">
<div class="item" v-slideIn v-for="(item, index) of 10" :key="index">
{{ index + 1 }}
</div>
</div>
</template>
<script>
export default {};
</script>
<style lang="scss">
.container {
width: 88%;
margin: 1rem auto;
.item {
width: 100%;
height: 300px;
margin-bottom: 20px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 3rem;
&:nth-child(3n-2) {
background-color: #fd524c;
}
&:nth-child(3n-1) {
background-color: #ffb527;
}
&:nth-child(3n) {
background-color: #23c039;
}
}
}
</style>
自定义指令
const DISTANCE = 150;
const DURATION = 1000;
const animationMap = new WeakMap();
const ob = new IntersectionObserver(entries => {
for (const entry of entries) {
if (entry.isIntersecting) { // isIntersecting这个属性判断元素是否与视口(或根元素)交叉
const animation = animationMap.get(entry.target);
animation.play();
ob.unobserve(entry.target);
}
}
})
// 判断元素是不是在视口之下
function isBelowViewport(el) {
const rect = el.getBoundingClientRect();
return rect.top > window.innerHeight;
}
export default {
inserted(el) {
if (!isBelowViewport(el)) {
return;
}
const animation = el.animate([
{
transform: `translateY(${DISTANCE}px)`,
opacity: 0.5
},
{
transform: 'translateY(0)',
opacity: 1
},
],
{
duration: DURATION,
easing: 'ease'
})
animation.pause(); // 暂停动画
animationMap.set(el, animation);
ob.observe(el);
},
unbind() {
ob.unobserve(el);
}
}