效果展示
vue文件的指令使用
css
复制代码
<style lang="scss">
.container {
width: 88%;
margin: 1rem auto;
.item {
background:url('../assets/boxImg.jpg') no-repeat;
background-size: 100% 100%;
width: 100%;
height: 300px;
margin-bottom: 20px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 3rem;
}
}
</style>
css
复制代码
<div class="container">
<div class="item" v-domSlown v-for="(item, index) in 10" :key="index" >
</div>
</div>
指令文件
javascript
复制代码
//domSlowness.js
import Vue from 'vue';
// 判断元素是不是在视口之下
function isBelowViewport(el) {
const rect = el.getBoundingClientRect();
return rect.top > window.innerHeight;
}
const DISTANCE = 150;
const DURATION = 1000;
const animationMap = new WeakMap();
const ob = new IntersectionObserver(entries => {
for (const entry of entries) {
if (entry.isIntersecting) { // 判断元素是否与视口交叉
const animation = animationMap.get(entry.target);
animation.play();
ob.unobserve(entry.target);
}
}
})
Vue.directive('domSlown',{
inserted(el,binding){
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(el) {
ob.unobserve(el);
}
})
主文件入口引用指令文件
javascript
复制代码
//main.js
import '@/assets/domSlowness.js'