我们继续 50 个小项目挑战!—— ScrollAnimation
组件
仓库地址:https://github.com/SunACong/50-vue-projects
项目预览地址:https://50-vue-projects.vercel.app/
在这篇文章中,我们将探索如何结合 Vue 的响应式能力与 TailwindCSS ,优雅地实现滚动触发的动画效果 。
Intersection Observer
+ 响应式 + 动态类向下滚动,内容块将从左或右滑入:
<template>
<div class="flex flex-col items-center justify-center gap-4 text-white">
<h1 class="head-text">Scroll to see the animationh1>
<div
v-for="(item, index) in contentList"
:key="item.id"
:ref="(el) => (boxRefs[index] = el)"
:class="[
'my-auto flex h-56 w-sm items-center justify-center rounded-2xl bg-white font-mono text-3xl font-bold text-black transition-all duration-700 ease-in md:w-md lg:w-lg',
index % 2 === 0 ? '-translate-x-full' : 'translate-x-full',
item.visible ? 'translate-x-0 opacity-100' : 'opacity-0'
]"
>
<div>{{ item.title }}div>
div>
div>
template>
<script setup>
import { ref, onMounted, reactive } from 'vue'
const boxRefs = reactive([])
const contentList = ref([
{ id: 1, title: 'Content 1', visible: false },
{ id: 2, title: 'Content 2', visible: false },
{ id: 3, title: 'Content 3', visible: false },
{ id: 4, title: 'Content 4', visible: false },
{ id: 5, title: 'Content 5', visible: false },
{ id: 6, title: 'Content 6', visible: false },
{ id: 7, title: 'Content 7', visible: false },
{ id: 8, title: 'Content 8', visible: false },
])
onMounted(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
const index = boxRefs.findIndex((ref) => ref === entry.target)
if (index !== -1) {
contentList.value[index].visible = entry.isIntersecting
}
})
},
{ threshold: 0.1 }
)
boxRefs.forEach((box) => {
if (box) observer.observe(box)
})
})
</script>
:class="[ item.visible ? 'translate-x-0' : '-translate-x-full' ]"
通过绑定 visible
状态,控制元素的滑入滑出。
状态 | 类名 | 作用 |
---|---|---|
初始状态 | opacity-0 scale-95 |
透明、稍小 |
可见状态 | opacity-100 scale-100 |
完全显示并放大到正常大小 |
滑入方向 | -translate-x-full / translate-x-full |
从左或右滑入 |
这个浏览器 API 用于监听元素是否进入视口,一旦进入就设置 item.visible = true
。
得益于 ref 和 reactive,我们可以无缝跟踪元素状态变化,自动更新 DOM。
通过 Vue + Tailwind,我们可以轻松实现丝滑的滚动动画,不仅无需外部库,而且还能保留极高的性能与响应式体验。
如果你也在构建自己的组件库或交互页面,不妨将这个模式作为模板来使用!
明日预告:Split Landing Page
!实现一个非常炫酷的丝滑的产品购买广告页面。