React之动画实现

一,介绍与需求

1.1,介绍

1,Ant Motion

Ant Motion能够快速在 React 框架中使用动画。在 React 框架下,只需要一段简单的代码就可以实现动画效果

2,SVG

  • SVG 指可伸缩矢量图形 (Scalable Vector Graphics)
  • SVG 用来定义用于网络的基于矢量的图形
  • SVG 使用 XML 格式定义图形
  • SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失
  • SVG 是万维网联盟的标准
  • SVG 与诸如 DOM 和 XSL 之类的 W3C 标准是一个整体

1.2,需求

提高网站的交互效果,提高用户体验。界面动效能加强用户认知且增加活力。

二,基于Ant Motion的react动画

2.1,动画效果

1,snow掉落效果

2,聚集与散开

2.2,动画实现方式

以掉落效果为例:

  1. import React from 'react';
  2. import Snow from './Snow';
  3. import './index.less';
  4. class App extends React.Component {
  5. constructor() {
  6. super(...arguments);
  7. this.state = {
  8. show: true,
  9. };
  10. }
  11. onEnd = () => {
  12. this.setState({
  13. show: false,
  14. });
  15. }
  16. render() {
  17. const children = Array(5).fill(1).map((c, i) => (
  18. <div key={i} className="addMoneyAnim" style={{ animationDelay: `${-Math.random() * 0.6}s` }} />
  19. ));
  20. return (
  21. <div className="snow-demo-wrapper" >
  22. <div className="snow-demo">
  23.  
  24. <Snow onEnd={this.onEnd} >
  25. {children}
  26. </Snow>
  27.  
  28. </div>
  29. </div>
  30. );
  31. }
  32. }
  33.  
  34. export default App;

组件snow代码:

  1. import React from 'react';
  2. import TweenOne from 'rc-tween-one';
  3. import BezierPlugin from 'rc-tween-one/lib/plugin/BezierPlugin';
  4. import PropTypes from 'prop-types';
  5.  
  6. import './index.less';
  7.  
  8. TweenOne.plugins.push(BezierPlugin);
  9.  
  10. class Snow extends React.Component {
  11. static propTypes = {
  12. children: PropTypes.any,
  13. className: PropTypes.string,
  14. prefixCls: PropTypes.string,
  15. amount: PropTypes.number,
  16. repeat: PropTypes.number,
  17. ease: PropTypes.string,
  18. startArea: PropTypes.object,
  19. endArea: PropTypes.object,
  20. startDelayRandom: PropTypes.number,
  21. basicToDuration: PropTypes.number,
  22. randomToDuration: PropTypes.number,
  23. rotateRandom: PropTypes.number,
  24. bezierSegmentation: PropTypes.number,
  25. onEnd: PropTypes.func,
  26. }
  27. static defaultProps = {
  28. prefixCls: 'snow',
  29. amount: 10,
  30. repeat: 0,
  31. ease: 'linear',
  32. startArea: {
  33. x: 0, y: -200, width: '100%', height: 50,
  34. },
  35. endArea: {
  36. x: -200, y: '100%', width: '120%', height: 100,
  37. },
  38. basicToDuration: 1200,
  39. randomToDuration: 800,
  40. startDelayRandom: 800,
  41. rotateRandom: 180,
  42. bezierSegmentation: 2,
  43. onEnd: () => { },
  44. };
  45.  
  46. constructor(props) {
  47. super(props);
  48. this.state = {
  49. children: null,
  50. };
  51. }
  52. componentDidMount() {
  53. this.setChilrenToState();
  54. }
  55.  
  56. onAnimEnd = () => {
  57. this.animEnd += 1;
  58. if (this.animEnd >= this.props.amount) {
  59. this.animEnd = 0;
  60. if (this.props.onEnd) {
  61. this.props.onEnd();
  62. }
  63. }
  64. }
  65.  
  66. setChilrenToState() {
  67. const children = this.getChildrenToRender();
  68. this.setState({
  69. children,
  70. });
  71. }
  72.  
  73. getChildrenToRender = () => {
  74. const {
  75. bezierSegmentation, basicToDuration, randomToDuration,
  76. amount, ease, startDelayRandom, repeat, rotateRandom,
  77. } = this.props;
  78. const children = React.Children.toArray(this.props.children);
  79. const rect = this.wrapperDom.getBoundingClientRect();
  80. const startArea = this.dataToNumber(this.props.startArea, rect);
  81. const endArea = this.dataToNumber(this.props.endArea, rect);
  82. return Array(amount).fill(1).map((k, i) => {
  83. const item = children[Math.floor(Math.random() * children.length)];
  84. const vars = Array(bezierSegmentation).fill(1).map((c, j) => {
  85. const hegiht = endArea.y - startArea.y - startArea.height;
  86. const y = (hegiht / bezierSegmentation) * (j + 1);
  87. const x = Math.random() * (Math.max(startArea.width, endArea.width)
  88. + Math.min(startArea.x, endArea.x));
  89. // console.log(hegiht, startArea, endArea, y);
  90. return {
  91. y,
  92. x,
  93. };
  94. });
  95. const delay = Math.random() * startDelayRandom;
  96. const animation = {
  97. bezier: {
  98. type: 'soft',
  99. autRotate: true,
  100. vars,
  101. },
  102. ease,
  103. repeat,
  104. repeatDelay: delay,
  105. delay,
  106. duration: basicToDuration + Math.random() * randomToDuration,
  107. onComplete: this.onAnimEnd,
  108. };
  109. const style = {
  110. transform: `translate(${Math.random() * (startArea.width) + startArea.x}px, ${
  111. Math.random() * (startArea.height) + startArea.y
  112. }px)`,
  113. };
  114. const child = rotateRandom ? (
  115. <TweenOne
  116. className="snowRotate"
  117. style={{ transform: `rotate(${Math.random() * rotateRandom}deg)` }}
  118. animation={{
  119. rotate: 0,
  120. duration: animation.duration * 4 / 5,
  121. delay: animation.delay,
  122. repeat: animation.repeat,
  123. }}
  124. >
  125. {item}
  126. </TweenOne>
  127. ) : item;
  128. return (
  129. <TweenOne
  130. animation={animation}
  131. style={style}
  132. key={`${item}-${i.toString()}`}
  133. className="snowChild"
  134. >
  135. {child}
  136. </TweenOne>
  137. );
  138. });
  139. }
  140. dataToNumber = (obj, rect) => {
  141. const toNumber = (v, full) => {
  142. if (typeof v === 'number') {
  143. return v;
  144. }
  145. const unit = v.replace(/[0-9|.]/g, '');
  146. switch (unit) {
  147. case '%':
  148. return parseFloat(v) * full / 100;
  149. case 'em':
  150. return parseFloat(v) * 16;
  151. default:
  152. return null;
  153. }
  154. };
  155. return {
  156. x: toNumber(obj.x, rect.width),
  157. y: toNumber(obj.y, rect.height),
  158. width: toNumber(obj.width, rect.width),
  159. height: toNumber(obj.height, rect.height),
  160. };
  161. }
  162. animEnd = 0;
  163. render() {
  164. const { prefixCls, ...props } = this.props;
  165. const { children } = this.state;
  166. [
  167. 'amount',
  168. 'repeat',
  169. 'ease',
  170. 'startArea',
  171. 'endArea',
  172. 'basicToDuration',
  173. 'randomToDuration',
  174. 'startDelayRandom',
  175. 'bezierSegmentation',
  176. 'rotateRandom',
  177. 'onEnd',
  178. ].forEach(k => delete props[k]);
  179. const className = `${prefixCls}${props.className ? ` ${props.className}` : ''}`;
  180. return (
  181. <div
  182. {...props}
  183. ref={(c) => {
  184. this.wrapperDom = c;
  185. }}
  186. className={className}
  187. >
  188. {children}
  189. </div>
  190. );
  191. }
  192. }
  193. export default Snow

样式代码:

  1. .snow-demo-wrapper {
  2. background: #DFEAFF;
  3. overflow: hidden;
  4. height: 500px;
  5. display: flex;
  6. align-items: center;
  7. position: relative;
  8. }
  9.  
  10. .snow-demo {
  11. width: 300px;
  12. height: %;
  13. margin: auto;
  14. position: relative;
  15. background-image: url(https://gw.alipayobjects.com/zos/rmsportal/dNpuKMDHFEpMGrTxdLVR.jpg);
  16. background-position: top;
  17. background-size: % auto;
  18. box-shadow: 32px rgba(, , , 0.15);
  19. }
  20.  
  21. .snow {
  22. width: %;
  23. height: %;
  24. position: absolute;
  25. top: ;
  26. overflow: hidden;
  27. }
  28.  
  29. .snowChild {
  30. position: absolute;
  31. top: ;
  32. left: ;
  33. }
  34.  
  35. .snowRotate {
  36. transform-origin: center center;
  37. }

2.3,动画分类

1,单元素动画rc-tween-one

  1. cnpm install rc-tween-one --save

2,css样式动画rc-animate

  1. cnpm install rc-animate --save

3,QueueAnim进出场动画

  1. cnpm install rc-queue-anim --save

4,TextyAnim文字动画

  1. cnpm install rc-texty --save

5,ScrollAnim页面滚动动画

  1. cnpm install rc-scroll-anim --save

6,Banner动画

  1. cnpm install rc-banner-anim --save

详细动画实例可查看官网

三,基于svg的react动画

3.1,动画效果

鼠标移入动画执行,鼠标移出动画停止

1,纵队动画

2,俄罗斯方块

3,坐标动画

3.2,动画实现方式

以纵队动画为例如下代码:

  1. import React from 'react';
  2. import Column from '../technology/Column';//实现动画的svg组件
  3.  
  4. export default class ReactAnimation extends React.Component {
  5. constructor(props) {
  6. super(props);
  7. this.state = {
  8. hover: null,//是否有鼠标的移入
  9. };
  10. }
  11.  
  12. onMouseEnter = (hover) => {//鼠标移入
  13. this.setState({
  14. hover,
  15. });
  16. };
  17. onMouseLeave = () => {//鼠标移出
  18. this.setState({
  19. hover: null,
  20. });
  21. };
  22. render() {
  23.  
  24. return (
  25. <div>
  26. <div
  27. onMouseEnter={() => { this.onMouseEnter(1); }}
  28. onMouseLeave={this.onMouseLeave}
  29. >
  30. <div>
  31. {Column && React.createElement(Column, {
  32. hover:this.state.hover === 1,
  33. })}
  34. </div>
  35. </div>
  36. </div>
  37. );
  38. }
  39. }

React.createElement(): 根据指定的第一个参数创建一个React元素。

  1. React.createElement(
  2. type,
  3. [props],
  4. [...children]
  5. )

第一个参数是必填,传入的是似HTML标签名称,如: ul, li 
第二个参数是选填,表示的是属性,如: className 
第三个参数是选填, 子节点,如: 要显示的文本内容

SVG配置组件Column.jsx:

  1. import React from 'react';
  2. import TweenOne from 'rc-tween-one';//引入动画插件
  3.  
  4. function TweenOneG(props) {
  5. function getAnimation() {
  6. return props.animation.map((item, i) => {
  7. return { ...item, duration: 400 };
  8. });
  9. }
  10. return (
  11. <TweenOne
  12. component="g"
  13. {...props}
  14. animation={
  15. props.animation ?
  16. getAnimation() :
  17. null
  18. }
  19. />);
  20. }
  21.  
  22. export default class Column extends React.PureComponent {
  23. render() {
  24. const { hover } = this.props;
  25. return (
  26. <svg width="328px" height="150px" viewBox="0 0 328 150">
  27. <defs>
  28. <linearGradient x1="50%" y1="3.05125957%" x2="50%" y2="157.404891%" id="linearGradient-1">
  29. <stop stopColor="#2898FF" offset="0%" />
  30. </linearGradient>
  31. </defs>
  32. <g id="Page-1" stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
  33. <TweenOneG animation={hover ? [{ y: -20 }, { y: -10 }, { y: -30 }] : this.default1Anim}>
  34. <g id="Group-33" transform="translate(0.000000, 116.000000)">
  35. <rect id="Rectangle-15" fill="#1890FF" opacity="0.03" x="0" y="2" width="20" height="145" />
  36. </g>
  37. </TweenOneG>
  38. </g>
  39. </svg>);
  40. }
  41. }

上面展示的只是部分代码,如需完整的代码,请先留言评论加关注

React之动画实现的更多相关文章

  1. React 附件动画API ReactCSSTransitionGroup

    React为动画提供了一个附加组件ReactTransitionGroup,这个附加组件是动画的底层API,并且还提供了一个附件组件ReactCSSTransitionGroup,ReactCSSTr ...

  2. React实现动画效果

    流畅.有意义的动画对于移动应用用户体验来说是非常必要的.和React Native的其他部分一样,动画API也还在积极开发中,不过我们已经可以联合使用两个互补的系统:用于全局的布局动画LayoutAn ...

  3. React Native动画总结

    最近在使用react native进行App混合开发,相对于H5的开发,RN所提供的样式表较少,RN中不能使用类似于css3中的动画,因此,RN提供了Animated的API 1.写一个最简单的动画 ...

  4. react过渡动画效果的实现,react-transition-group

    本文介绍react相关的过渡动画效果的实现 有点类似vue的transition组件,主要用于组件mount和unmount之前切换时应用动画效果 安装 cnpm install react-tran ...

  5. react react-smooth动画

    首先自然而然的安装一下依赖: npm install react-smooth --save-dev 接下来就是组件代码啦: import React, { Component, Fragment } ...

  6. 用react的ReactCSSTransitionGroup插件实现简单的弹幕动画

    1,开始的思路 公司想做直播方面的项目,并想加入弹幕的功能,直播的页面已经作为一个组件放在了用react+redux写好的一个网站项目上.所以技术老大让我研究下如何用react实现弹幕的功能.下面我就 ...

  7. 慢牛系列四:好玩的React Native

    在上次随笔(系列三)中,我试着用RN实现了一个Demo,感觉很不错,当时遇到的问题这篇文章里基本都解决了,比如导航动画问题,这篇文章里主要介绍RN的动画,学会动画以后,各种小创意都可以实现了^^ 下面 ...

  8. ReactNative学习实践--动画初探之加载动画

    学习和实践react已经有一段时间了,在经历了从最初的彷徨到解决痛点时的兴奋,再到不断实践后遭遇问题时的苦闷,确实被这一种新的思维方式和开发模式所折服,react不是万能的,在很多场景下滥用反而会适得 ...

  9. React 读书笔记

    序言: 领导安排部门同事本月内看一本跟自己职业相关的书籍, 根基类的书籍已经看过了,重复阅读的意义不大,所以我平时看的都是视频,也许是视频作者没有出书的条件,也许是现在出书看的人越来越少了,也许有其他 ...

随机推荐

  1. python查询elasticsearch(Query DSL) 实例

    import datetime import sys import getopt import hashlib from elasticsearch import Elasticsearch &quo ...

  2. Codeforces Gym101518E:The Pharaoh's Curse(BFS + 离散化)

    题目链接 题意 给出一个n*m的地图,人的当前位置是'S',还有不超过两个的箱子'X',任意多个按钮'B',不超过100个可以走的点'.',还有一个在边界的出口'E',当且仅当所有的按钮都被箱子盖住的 ...

  3. 用链表和数组实现HASH表,几种碰撞冲突解决方法

    Hash算法中要解决一个碰撞冲突的办法,后文中描述了几种解决方法.下面代码中用的是链式地址法,就是用链表和数组实现HASH表. he/*hash table max size*/ #define HA ...

  4. c++学习书籍推荐《Visual C++2008入门经典》下载

    百度云及其他网盘下载地址:点我 <Visual C++2008入门经典>学习目标: 使用标准模板库(STL)来组织和操作本地C++程序中的数据 C++程序调试技术 构造Microsoft ...

  5. 主机地址变更后,dubbo请求时依旧会寻址旧IP的问题

    机房迁移,导致测试服务器IP变更,比原于IP为192.168.1.105变更为10.1.9.120. 服务源码未做任何变更,启动服务时依旧是旧地址请求,此问题由dubbo本地注册中心的缓存所致,清理掉 ...

  6. mysql in与exists问题剖析

    1 问题描述 ​ 发布当天发现一个日志分析的sql,在测试环境上执行良好,1秒内,而在线上环境上,执行要13秒左右. 嵌套sql一步一步分析后,发现出在in上,因时间紧迫,来补不及具体分析原因,尝试使 ...

  7. 20140115-URL编码与解码

    UrlEncode()方法,有两个类都有这个方法即HttpUtility.UrlEncode和Server.UrlEncode 区别: 1.HttpUtility.UrlEncode,HttpUtil ...

  8. FC游戏修改教程(hack)小白文。

    FC(NES)红白机Family Computer(简称FAMICOM)(或Nintendo Entertainment System)是任天堂公司发行的第一代家用游戏机. 修改FC游戏需要的工具有 ...

  9. 个人永久性免费-Excel催化剂功能第101波-批量替换功能(增加正则及高性能替换能力)

    数据处理无小事,正如没有人活在真空理想环境一下,在数据分析过程中,也没有那么真空理想化的数据源可以使用,数据处理占据数据分析的80%的时间,每一个小小的改善,获益都良多.Excel查找替换,有其局限性 ...

  10. 个人永久性免费-Excel催化剂功能第69波-专业图表库新增图表-刘万祥老师中国地图

    Excel催化剂的[专业图表库],仅提供一个工具的输出,让用户可以在制作专业图表过程中更低的门槛,更快速的完成所想要实现的图表.具体参考:第69波-打造最专业易用的商务图表库https://www.j ...