使用IntersectionObserver制作滚动动画以及其他记录

时间:2024-11-06 16:34:26

前言

最近在重做公司项目的主页,正好新来了个UI,整个都重新设计了一下,动画还挺多的。我之前没有怎么玩过这些,踩了挺多坑,最后找到了目前而言最合适的方法,现在做一个记录。

需要把原来的主页从项目中抽出来,所以干脆重新建了一个项目,使用vuecli4搭配ts,顺便踩一踩vue-ts的坑。

进入正题

需求之一是要有滚动动画,即当滚动到某个地方时播放动画,传统的方式是根据scroll距离判断滚动位置,当然可以用,不过还有其他方法可以做。

使用 IntersectionObserver api可以在很少代码量的情况下实现要求,我想既然他能做懒加载,做滚动动画应该绰绰有余。

在vue中使用IntersectionObserver

可以使用选择dom的方式,也可以使用更通用的方法,这里介绍通用方法

建一个ts文件

这里observe滚动,一旦元素达到可视区域,即加入enter class

之后unobserve,该动画只播放一次

const animatedScrollObserver: IntersectionObserver = new IntersectionObserver(
(entries,animatedScrollObserver) => {
entries.forEach((e): any => {
if (e.isIntersecting) {
e.target.classList.add('enter');
animatedScrollObserver.unobserve(e.target);
}
});
}
)

接下来export出去,只要传入一个dom,就可以observe该元素

export default {
bind(el: any) {
el.classList.add('before-enter');
animatedScrollObserver.observe(el); }
}

在main.ts中引入,并且自定义指令,我们可以使用v-sa来引入需要observe的元素

import ScrollAnimation from "./ts/animation/scrollAnimation";

Vue.directive('sa',ScrollAnimation)

到这里工作基本完成,接下来可以设置一些动画,这些动画将在滚动到元素第一次时被播放

举例:html部分

<template>
<div id="container">
<!-- 省略 -->
<section class="text-wrapper">
<p v-sa>lorem ipsum之类的展位字符,.......</p>
</section>
<section class="pic-wrapper">
<img v-sa src="..." />
</section>
<!-- ..省略.. -->
</div>
</template>

css部分

// 文字从左侧缓入
.text-wrapper{
@keyframes moveup {
from {
left: -15px;
} to {
top: 0;
}
}
.before-enter{
opacity: 0;
}
.enter {
opacity: 1;
animation: moveup 3s;
}
p {
position: relative;
}
}
// 图片从下往上
.pic-wrapper{
@keyframes moveup {
from {
top: 30px;
} to {
top: 0;
}
}
.before-enter{
opacity: 0;
}
.enter {
opacity: 1;
animation: moveup 2s;
}
img {
position: relative;
}
}

关于vue ts的一些吐槽

ts是真香,但是目前vue对ts支持还不太好,比如引入外部js模块,需要在d.ts中declare module(还经常出问题),有些cdn方式引入的库,即便设置了vue.config.js中的externals,还是识别不了。可能是有些我还没研究透,但是足以体现支持不佳的现状。希望能在将来的vue3正式版中有所改进。