Framer Motion第二弹,动画效果的创意实现!Framer Motion第二弹,动画效果的创意实现! 上一章节刚
上一章节刚介绍了Framer Motion
,这不昨天无意间看到了一个网站的动画效果,今天使用Framer Motion
来实现一下。
效果地址:steam-portfolio-demo.vercel.app/
效果分析
动画并不复杂,但是应用到网站中使得网站看起来比较有活力,整体效果很好。
这个效果包含两个动画:
- 动画一:内容从底部弹出,并且伴随着透明度的改变
- 动画二:遮罩层从左向右退出
我们直接使用Framer Motion
来实现这个效果,如果对该库不了解的可以阅读上一篇文章。
效果实现
这个效果是应用到网站的内容上面,会多处使用,所以使用组件实现;这里要使用组合动画
、variants
以及两个钩子函数useAnimation、useInView
。
- useAnimation:返回一个控制动画的对象,可以使用它来手动触发、停止或修改动画。对于需要在事件(如点击、悬停)中动态控制动画的场景特别有用。
- useInView:用于检测一个组件是否在视口中。通常用于触发滚动进入视图时的动画。
我们先来实现上面提到的动画一:
//改变透明度和纵向的位置
const variantsMain = {
hidden: { opacity: 0, y: 75 },
visible: { opacity: 1, y: 0 },
};
//动画组件
<div ref={ref} style={{ position: "relative", width, overflow: "hidden", ...style }}>
<motion.div
variants={variantsMain}
initial="hidden"
animate={mainControls}
transition={{ duration: 0.5, delay: 0.25 }}
>
{/* 网站内容 */}
{children}
</motion.div>
</div>
animate
属性由visible
字符串设置为控制动画的对象mainControls
,通过元素是否出现在视口来执行相应的动画:
const ref = useRef(null);
const isInView = useInView(ref);
const mainControls = useAnimation();
useEffect(() => {
if (isInView) {
mainControls.start("visible");
} else {
mainControls.start("hidden");
}
}, [isInView]);
这样动画一就完成了,动画二实现思路和一相同,我直接把动画组件MotionView的代码贴在下面:
import React, { memo, useEffect, useRef } from "react";
import { motion, useAnimation, useInView } from "framer-motion";
import { useThemeToken } from "@/theme/hooks";
interface Props {
children: React.ReactNode;
width?: "fit-content" | "100%";
style?: React.CSSProperties;
}
const variantsMain = {
hidden: { opacity: 0, y: 75 },
visible: { opacity: 1, y: 0 },
};
const variantsSlide = {
hidden: { left: 0 },
visible: { left: "100%" },
};
const MotionView = memo(({ width = "fit-content", children, style = {} }: Props) => {
const ref = useRef(null);
const isInView = useInView(ref);
const mainControls = useAnimation();
const slideControls = useAnimation();
const { colorPrimary } = useThemeToken();
useEffect(() => {
if (isInView) {
mainControls.start("visible");
slideControls.start("visible");
} else {
mainControls.start("hidden");
slideControls.start("hidden");
}
}, [isInView]);
return (
<div ref={ref} style={{ position: "relative", width, overflow: "hidden", ...style }}>
<motion.div
variants={variantsMain}
initial="hidden"
animate={mainControls}
transition={{ duration: 0.5, delay: 0.25 }}
>
{children}
</motion.div>
<motion.div
variants={variantsSlide}
initial="hidden"
animate={slideControls}
transition={{ duration: 0.5, ease: "easeIn" }}
style={{
position: "absolute",
top: 4,
bottom: 0,
left: 0,
right: 0,
background: colorPrimary,
zIndex: 10,
}}
/>
</div>
);
});
export default MotionView;
使用动画到网站内容:
<MotionView>
<div>Hey, I'm LEOPAI.</div>
</MotionView>
<MotionView>
<div>
I'm a <span style={{ color: colorPrimary }}>Front-end Developer, React Developer</span>
</div>
</MotionView>
我随便画了案例网站中的一些元素来实现整体效果,录制了一段视频来展示一下:
无法上传,请移步公众号观看。
我加入了主题色,可以改变主题色来改变动画的颜色。我这里设置的是元素离开视口就退出动画回到初始状态,和案例网站中不同,如果想像案例的网站一样只执行一次,可以使用once
选项:
const isInView = useInView(ref, { once: true });
介绍完毕,感谢您的阅读!
转载自:https://juejin.cn/post/7401066742069690380