优美的Reactl列表动画:Styled-Components动画实践

简介: 优美的Reactl列表动画:Styled-Components动画实践

先看效果图(录制软件限制,只有30祯,真实效果可以运行源码)

基础动画如下:image.png

组合动画如下:

b5d5f20d537c4c9fb969422ae8923aa8~tplv-k3u1fbpfcp-zoom-in-crop-mark_1512_0_0_0.gif

带缩放的动画如下:e9dbf21dbe19407f8cf770ad1e17f8df~tplv-k3u1fbpfcp-zoom-in-crop-mark_1512_0_0_0.gif

1 动画实现的基本原理

所谓万变不离其宗,我们的动画底层还是依靠css提供的animation动画

animation: name duration timing-function delay iteration-count direction fill-mode play-state;
@keyframes name {
  0% {}
  100% {}
}

fill-mode规定当动画不播放时(当动画完成时,或当动画有一个延迟未开始播放时),要应用到元素的样式

默认为none:在动画执行之前和之后不会应用任何样式到目标元素,即采用初始样式

forwards:将动画结束之后的样式应用在元素上,即不采用初始样式

2 和styled-components结合起来

主要采用styled-components(CSS in JS方案)提供的styled方法定义CSS animation动画参数,配合提供的keyframes方法定义各种类型动画实现,

例如,定义一个从底往上进入的动画

import styled, { keyframes } from "styled-components";
const bottomToTop = keyframes`
  0% {
    transform: translateY(50%);
  }
  100% {
    transform: translateY(0);
  }
`
export const BottomToTop = styled.div`
  transform: translateY(50%);
  animation: ${bottomToTop} 300ms;
  animation-iteration-count: 1;
  animation-fill-mode: forwards;
  animation-delay: 150ms;
`

为了让每个列表项的动画开错落有序,还需要将动画的延时时间做下处理

animation-delay: ${props => (props.index ?? 0) * 150}ms

为了更灵活的使用,将延时参数、动画时长参数,设置为动态的变量

animation: ${bottomToTop} ${props => props.duration ?? 300}ms;
animation-delay: ${props => (props.index ?? 0) * (props.delay ?? 150)}ms

即完整的动画定义为下面这样

import styled, { keyframes } from "styled-components";
export interface AnimationProps {
  index?: number
  duration?: number
  delay?: number
}
const bottomToTop = keyframes`
  0% {
    transform: translateY(50%);
  }
  100% {
    transform: translateY(0);
    opacity: 1
  }
`
export const BottomToTop = styled.div<AnimationProps>`
  transform: translateY(50%);
  opacity: 0;
  animation: ${bottomToTop} ${props => props.duration ?? 300}ms;
  animation-iteration-count: 1;
  animation-fill-mode: forwards;
  animation-delay: ${props => (props.index ?? 0) * (props.delay ?? 150)}ms
`

接着在列表渲染的地方使用BottomToTop组件

const App: () => {
  return <>
        // ...
       {
        new Array(5).fill(null).map((_, idx) => <BottomToTop key={idx} index={idx}>
          <YourComponents />
        </BottomToTop>)
      }
  </>
}

此时动画样式虽然很舒服了,但是还不够优雅

我们给动画加个回弹动画

const bottomToTop = keyframes`
  0% {
    transform: translateY(50%);
  }
  80% {
    transform: translateY(-10%);
  }
  100% {
    transform: translateY(0);
  }
`

这样动画就更加有灵性了

实现其余基础动画的方式与此类似,具体可以参考源码

下面展示下组合动画的

3 思路打开

除了逐个有序的渲染列表,我们还可以考虑按照一定规律给不同的元素使用不同的话,

3.1 左右交错

例如,如果是奇数项,元素就从右边进入,如果是偶数项,就从左边进入

const App: () => {
  return <>
        // ...
       {
        new Array(5).fill(null).map((_, idx) => idx % 2 === 0
          ? <RightToLeft key={idx} index={idx} duration={300} delay={50}>
              <YourComponents />
            </RightToLeft>
          : <LeftToRight key={idx} index={idx} duration={300} delay={50}>
              <YourComponents />
          </LeftToRight>)
      }
  </>
}

3.2 上下交错

例如,如果是奇数项,元素就从上边进入,如果是偶数项,就从下边进入

const App: () => {
  return <>
        // ...
       {
        new Array(5).fill(null).map((_, idx) => idx % 2 === 0
          ? <TopToBottom key={idx} index={idx} duration={300} delay={50}>
              <YourComponents />
            </TopToBottom>
          : <BottomToTop key={idx} index={idx} duration={300} delay={50}>
              <YourComponents />
          </BottomToTop>)
      }
  </>
}

3.3 左右交错的同时载增加从下到上的动画

甚至,你还可以给交错的列表增加点别的动画,例如左右交错的同时载增加从下到上的动画

const App: () => {
  return <>
        // ...
       {
        new Array(5).fill(null).map((_, idx) => idx % 2 === 0
          ? <BottomToTop key={idx} index={idx} duration={300} delay={50}>
              <RightToLeft index={idx} duration={300} delay={50}>
                <YourComponents />
              </RightToLeft>
            </BottomToTop>
          : <BottomToTop key={idx} index={idx} duration={300} delay={50}>
              <LeftToRight index={idx} duration={300} delay={50}>
                <YourComponents />
              </LeftToRight>
            </BottomToTop>
         )
      }
  </>
}

4 思路再打开

我们不要局限于仅有的translateXtranslateYtranslate属性,还可以尝试下其余的动画属性,例如,我使用scale属性增加了缩放动画,组合我们列表动画,效果如下

const scale = keyframes`
  0% {
    transform: scale(0.8);
  }
  70% {
    transform: scale(1.2);
  }
  100% {
    transform: scale(1);
    opacity: 1
  }
`
export const Scale = styled.div<AnimationProps>`
  transform: scale(1);
  opacity: 0;
  animation: ${scale} ${props => props.duration ?? 300}ms;
  animation-iteration-count: 1;
  animation-fill-mode: forwards;
  animation-delay: ${props => (props.index ?? 0) * (props.delay ?? 150)}ms
`

从上面你或许可以看到,我的组合动画似乎比较繁琐,例如,从左到右同时从下到上,我使用了translateXtranslateY组合,而不是直接定义translate,其实我考虑到基础动画,组合起来使用场景更广,所以就这样使用了,当然,如果需要,你也可以单独加上这样的基础动画。

如果你有更好的思路,欢迎交流

相关文章
|
10天前
|
前端开发 JavaScript API
Nuxt3 实战 (十一):添加路由 Transition 过渡效果和 Loading 动画
这篇文章介绍了Nuxt3框架中页面和布局的过渡效果设置方法,以及首屏加载动画的添加。通过配置nuxt.config.ts文件和添加CSS样式,可以实现页面过渡效果。同时,文章也提到了在页面中设置不同的过渡效果和为布局和页面同时设置过渡效果的方法。最后,文章以一个Github仓库链接和一个线上预览地址作为总结,表示遵循官方文档操作即可完成相关设置。
Nuxt3 实战 (十一):添加路由 Transition 过渡效果和 Loading 动画
|
2月前
|
移动开发 小程序 JavaScript
uniapp中uview组件库丰富的Slider 滑动选择器的使用方法
uniapp中uview组件库丰富的Slider 滑动选择器的使用方法
101 1
|
2月前
|
移动开发 小程序 API
uniapp中uview组件库中丰富的LineProgress 线形进度条 的使用方法
uniapp中uview组件库中丰富的LineProgress 线形进度条 的使用方法
61 1
|
2月前
|
JavaScript 前端开发
jQuery 第五章(效果,滑动,动画,停止动画)
jQuery 第五章(效果,滑动,动画,停止动画)
60 0
|
前端开发
滚动页面触发相应位置动画 ---react
滚动页面触发相应位置动画 ---react
|
前端开发 JavaScript
学习Vue3 第二十一章(transition动画组件)
自定义 transition 过度效果,你需要对transition组件的name属性自定义。并在css中写入对应的样式
314 0
|
资源调度 前端开发
React实现拖拽改变宽度
React实现拖拽改变宽度
React实现拖拽改变宽度
|
JavaScript 开发者
动画-使用 transition-group 元素实现列表动画|学习笔记
快速学习动画-使用 transition-group 元素实现列表动画
118 0
动画-使用 transition-group 元素实现列表动画|学习笔记
|
JavaScript 开发者
动画-使用transition-group元素实现列表动画|学习笔记
快速学习动画-使用transition-group元素实现列表动画
109 0
动画-使用transition-group元素实现列表动画|学习笔记
|
JavaScript
【Vue3从零开始-第四章】4-5 列表动画和状态动画
【Vue3从零开始-第四章】4-5 列表动画和状态动画
136 0
【Vue3从零开始-第四章】4-5 列表动画和状态动画