Appearance
观察者实现滚动动画
演示
向下滚动查看效果
<template>
<div class="container">
<div class="full">
向下滚动查看效果
</div>
<div class="box-container" ref="boxContainer">
<div v-for="item in list" :key="item.id" class="box hide" :style="item.style">
</div>
</div>
</div>
</template>
<script setup lang='ts'>
import { ref, onMounted } from 'vue';
defineOptions({
name: 'observer',
});
// 生成随机颜色
const randomColor = () => {
const chars = "1234567890abcdef",
colorLength = 6;
let color = '#';
for (let i = 0; i < colorLength; i++) {
const p = Math.floor(Math.random() * chars.length);
color += chars.substring(p, p + 1);
};
return color;
};
// 生成列表数据
const list = Array.from({ length: 60 }, (v, i) => i).map((v) => ({
id: v,
style: {
backgroundColor: randomColor(),
'border-radius': '5px',
width: '80px',
height: '80px',
'margin-bottom': '10px',
},
}));
// 盒子容器
const boxContainer = ref<HTMLElement | null>(null);
onMounted(() => {
if (boxContainer.value) {
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
const dom = entry.target as HTMLElement;
const isIntersecting = entry.isIntersecting
dom.classList.add(isIntersecting ? 'show' : 'hide');
dom.classList.remove(isIntersecting ? 'hide' : 'show');
if (isIntersecting) observer.unobserve(dom)
});
}, {
threshold: 0.1,
});
const boxs = boxContainer.value.querySelectorAll('.box-container > div');
boxs.forEach((box) => {
observer.observe(box);
});
}
})
</script>
<style lang='scss' scoped>
.container {
justify-content: space-between;
width: 100%;
min-width: 300px;
height: 400px;
overflow: auto;
background-color: rgba($color: #000000, $alpha: 1);
.full {
width: 100%;
height: 400px;
line-height: 400px;
text-align: center;
font-weight: 700;
font-size: 20px;
color: #fff;
}
.box-container {
margin: 0 auto;
justify-content: space-around;
display: flex;
flex-wrap: wrap;
width: 300px;
.box {
transition: all 0.5s;
}
.box:nth-child(3n + 1) {
transform: translate(-100px, 0) scale(0);
}
.box:nth-child(3n + 2) {
transform: translate(0, 0px) scale(0);
}
.box:nth-child(3n + 3) {
transform: translate(100px, 0) scale(0);
}
.box.show {
opacity: 1;
transform: translate(0, 0);
}
}
}
</style>