vue3指令实现通用元素平滑上升效果
可通过Animation API定义元素平滑上升动画,目的防止与元素原有的css样式起冲突,实现具有通用性的元素平滑上升指令
<template>
<div class="container">
<div v-slide-in class="item">1</div>
<div v-slide-in class="item">2</div>
<div v-slide-in class="item">3</div>
<div v-slide-in class="item">4</div>
</div>
</template>
<style scoped>
.container{
margin:1em auto;
width:80%;
}
.item{
width:100%
height:500px;
background:blue;
}
</style>
//定义vSildeIn.js
const distance = 150;
const duration = 1000;
//WeakMap避免内存泄露
cosnt animationMap = new WeakMap();
//监听元素是否与当前页面视口重叠,即判断元素是否出现于当前视口内,返回所有元素监听结果
const ob = new IntersectionObserver(entries=>{
for(const entry of entrise){
//判断元素是否在视口内
if(entry.isIntersecting){
//获取当前在视口内的元素动画对象
const animation = animationMap.get(entry.target);
//开始执行动画
animation.play();
//执行完后取消监听,限制动画只播放一次,防止回滚时重复播放
ob.unobserver(entry.target);
}
}
})
//判断元素是否在视口之下
function isBelowViewPort(el){
const rect = el.getBoundingClientRect();
return rect.top > window.innerHeight;
}
export default {
mounted(el){
if(!isBelowViewPort(el)){
return;
}
const animation = el.animate([
//配置关键帧start
{
transform: `translateY(${distance})`,
opcaity: 0.5,
},
{
transform: `translateY(0)`,
opcaity: 1,
}
//配置关键帧end
],{
//配置动画执行时间
duration: duration,
//配置动画时间函数
easing: 'ease-in-out',
});
//起始状态暂停动画执行,待元素在视口范围内执行动画
animation.pause();
//将元素与对象绑定进行映射
animationMap.set(el,animation);
//监听动画是否与视口重叠
ob.observe(el)
},
//元素卸载时取消监听
unmounted(el){
ob.unobserve(el);
}
}