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,动画实现方式

以掉落效果为例:

 import React from 'react';
import Snow from './Snow';
import './index.less';
class App extends React.Component {
constructor() {
super(...arguments);
this.state = {
show: true,
};
}
onEnd = () => {
this.setState({
show: false,
});
}
render() {
const children = Array(5).fill(1).map((c, i) => (
<div key={i} className="addMoneyAnim" style={{ animationDelay: `${-Math.random() * 0.6}s` }} />
));
return (
<div className="snow-demo-wrapper" >
<div className="snow-demo"> <Snow onEnd={this.onEnd} >
{children}
</Snow> </div>
</div>
);
}
} export default App;

组件snow代码:

   import React from 'react';
import TweenOne from 'rc-tween-one';
import BezierPlugin from 'rc-tween-one/lib/plugin/BezierPlugin';
import PropTypes from 'prop-types'; import './index.less'; TweenOne.plugins.push(BezierPlugin); class Snow extends React.Component {
static propTypes = {
children: PropTypes.any,
className: PropTypes.string,
prefixCls: PropTypes.string,
amount: PropTypes.number,
repeat: PropTypes.number,
ease: PropTypes.string,
startArea: PropTypes.object,
endArea: PropTypes.object,
startDelayRandom: PropTypes.number,
basicToDuration: PropTypes.number,
randomToDuration: PropTypes.number,
rotateRandom: PropTypes.number,
bezierSegmentation: PropTypes.number,
onEnd: PropTypes.func,
}
static defaultProps = {
prefixCls: 'snow',
amount: 10,
repeat: 0,
ease: 'linear',
startArea: {
x: 0, y: -200, width: '100%', height: 50,
},
endArea: {
x: -200, y: '100%', width: '120%', height: 100,
},
basicToDuration: 1200,
randomToDuration: 800,
startDelayRandom: 800,
rotateRandom: 180,
bezierSegmentation: 2,
onEnd: () => { },
}; constructor(props) {
super(props);
this.state = {
children: null,
};
}
componentDidMount() {
this.setChilrenToState();
} onAnimEnd = () => {
this.animEnd += 1;
if (this.animEnd >= this.props.amount) {
this.animEnd = 0;
if (this.props.onEnd) {
this.props.onEnd();
}
}
} setChilrenToState() {
const children = this.getChildrenToRender();
this.setState({
children,
});
} getChildrenToRender = () => {
const {
bezierSegmentation, basicToDuration, randomToDuration,
amount, ease, startDelayRandom, repeat, rotateRandom,
} = this.props;
const children = React.Children.toArray(this.props.children);
const rect = this.wrapperDom.getBoundingClientRect();
const startArea = this.dataToNumber(this.props.startArea, rect);
const endArea = this.dataToNumber(this.props.endArea, rect);
return Array(amount).fill(1).map((k, i) => {
const item = children[Math.floor(Math.random() * children.length)];
const vars = Array(bezierSegmentation).fill(1).map((c, j) => {
const hegiht = endArea.y - startArea.y - startArea.height;
const y = (hegiht / bezierSegmentation) * (j + 1);
const x = Math.random() * (Math.max(startArea.width, endArea.width)
+ Math.min(startArea.x, endArea.x));
// console.log(hegiht, startArea, endArea, y);
return {
y,
x,
};
});
const delay = Math.random() * startDelayRandom;
const animation = {
bezier: {
type: 'soft',
autRotate: true,
vars,
},
ease,
repeat,
repeatDelay: delay,
delay,
duration: basicToDuration + Math.random() * randomToDuration,
onComplete: this.onAnimEnd,
};
const style = {
transform: `translate(${Math.random() * (startArea.width) + startArea.x}px, ${
Math.random() * (startArea.height) + startArea.y
}px)`,
};
const child = rotateRandom ? (
<TweenOne
className="snowRotate"
style={{ transform: `rotate(${Math.random() * rotateRandom}deg)` }}
animation={{
rotate: 0,
duration: animation.duration * 4 / 5,
delay: animation.delay,
repeat: animation.repeat,
}}
>
{item}
</TweenOne>
) : item;
return (
<TweenOne
animation={animation}
style={style}
key={`${item}-${i.toString()}`}
className="snowChild"
>
{child}
</TweenOne>
);
});
}
dataToNumber = (obj, rect) => {
const toNumber = (v, full) => {
if (typeof v === 'number') {
return v;
}
const unit = v.replace(/[0-9|.]/g, '');
switch (unit) {
case '%':
return parseFloat(v) * full / 100;
case 'em':
return parseFloat(v) * 16;
default:
return null;
}
};
return {
x: toNumber(obj.x, rect.width),
y: toNumber(obj.y, rect.height),
width: toNumber(obj.width, rect.width),
height: toNumber(obj.height, rect.height),
};
}
animEnd = 0;
render() {
const { prefixCls, ...props } = this.props;
const { children } = this.state;
[
'amount',
'repeat',
'ease',
'startArea',
'endArea',
'basicToDuration',
'randomToDuration',
'startDelayRandom',
'bezierSegmentation',
'rotateRandom',
'onEnd',
].forEach(k => delete props[k]);
const className = `${prefixCls}${props.className ? ` ${props.className}` : ''}`;
return (
<div
{...props}
ref={(c) => {
this.wrapperDom = c;
}}
className={className}
>
{children}
</div>
);
}
}
export default Snow

样式代码:

 .snow-demo-wrapper {
background: #DFEAFF;
overflow: hidden;
height: 500px;
display: flex;
align-items: center;
position: relative;
} .snow-demo {
width: 300px;
height: %;
margin: auto;
position: relative;
background-image: url(https://gw.alipayobjects.com/zos/rmsportal/dNpuKMDHFEpMGrTxdLVR.jpg);
background-position: top;
background-size: % auto;
box-shadow: 32px rgba(, , , 0.15);
} .snow {
width: %;
height: %;
position: absolute;
top: ;
overflow: hidden;
} .snowChild {
position: absolute;
top: ;
left: ;
} .snowRotate {
transform-origin: center center;
}

2.3,动画分类

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

 cnpm install rc-tween-one --save

2,css样式动画rc-animate

 cnpm install rc-animate --save

3,QueueAnim进出场动画

 cnpm install rc-queue-anim --save

4,TextyAnim文字动画

 cnpm install rc-texty --save

5,ScrollAnim页面滚动动画

 cnpm install rc-scroll-anim --save

6,Banner动画

 cnpm install rc-banner-anim --save

详细动画实例可查看官网

三,基于svg的react动画

3.1,动画效果

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

1,纵队动画

2,俄罗斯方块

3,坐标动画

3.2,动画实现方式

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

 import React from 'react';
import Column from '../technology/Column';//实现动画的svg组件 export default class ReactAnimation extends React.Component {
constructor(props) {
super(props);
this.state = {
hover: null,//是否有鼠标的移入
};
} onMouseEnter = (hover) => {//鼠标移入
this.setState({
hover,
});
};
onMouseLeave = () => {//鼠标移出
this.setState({
hover: null,
});
};
render() { return (
<div>
<div
onMouseEnter={() => { this.onMouseEnter(1); }}
onMouseLeave={this.onMouseLeave}
>
<div>
{Column && React.createElement(Column, {
hover:this.state.hover === 1,
})}
</div>
</div>
</div>
);
}
}

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

 React.createElement(
type,
[props],
[...children]
)

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

SVG配置组件Column.jsx:

 import React from 'react';
import TweenOne from 'rc-tween-one';//引入动画插件 function TweenOneG(props) {
function getAnimation() {
return props.animation.map((item, i) => {
return { ...item, duration: 400 };
});
}
return (
<TweenOne
component="g"
{...props}
animation={
props.animation ?
getAnimation() :
null
}
/>);
} export default class Column extends React.PureComponent {
render() {
const { hover } = this.props;
return (
<svg width="328px" height="150px" viewBox="0 0 328 150">
<defs>
<linearGradient x1="50%" y1="3.05125957%" x2="50%" y2="157.404891%" id="linearGradient-1">
<stop stopColor="#2898FF" offset="0%" />
</linearGradient>
</defs>
<g id="Page-1" stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
<TweenOneG animation={hover ? [{ y: -20 }, { y: -10 }, { y: -30 }] : this.default1Anim}>
<g id="Group-33" transform="translate(0.000000, 116.000000)">
<rect id="Rectangle-15" fill="#1890FF" opacity="0.03" x="0" y="2" width="20" height="145" />
</g>
</TweenOneG>
</g>
</svg>);
}
}

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

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. MyBatis从入门到精通(六):MyBatis动态Sql之if标签的用法

    最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 本篇博客主要讲解如何使用if标签生成动 ...

  2. Golang之mirco框架部分浅析

    在实习中使用 micro 框架,但是挺多不懂的,看了部分源码搞懂了一些,还是有一些比较复杂没搞懂. 第一部分:初始化 service 并修改端口 main.go // waitgroup is a h ...

  3. Hyperledger Fabric 命令整理

    Peer节点命令 Peer node start 启动一个Peer节点: peer node start status 获取当前节点的状态信息 peer node status reset 重置当前节 ...

  4. C++学习书籍推荐《C++编程思想第二版第二卷》下载

    百度云及其他网盘下载地址:点我 编辑推荐 “经典原版书库”是响应教育部提出的使用原版国外教材的号召,为国内高校的计算机教学度身订造的.<C++编程思想>(英文版第2版)是书库中的一本,在广 ...

  5. Win10更新后,MySQL服务莫名消失的问题

    手欠的给Win10更新,之后就发现右下角托盘里的小海豚变成白色的了,最后确认MySQL服务丢失 解决办法1: 1.重新安装服务:mysqld --install 2.如果之前没有自定义数据保存路径(d ...

  6. GitHub使用整理——从开始到上传项目

    前期准备 首先是github官网: https://github.com/ 下载github工具: https://git-for-windows.github.io/ 进入github创建一个新的项 ...

  7. 【题解】【合并序列(水题)P1628】

    原题链接 这道题目如果连字符串的基本操作都没学建议不要做. 学了的很简单就可以切,所以感觉没什么难度- 主要讲一下在AC基础上的优化(可能算不上剪枝) 很明显,这道题我们要找的是前缀,那么在字符串数组 ...

  8. py+selenium 报错NameError: name 'NoSuchElementException' is not defined【已解决】

     报错:NameError: name 'NoSuchElementException' is not defined  如图 解决方法: 头部加一句:from selenium.common.exc ...

  9. [ERROR]:INST-07008: Oracle 主目录(O) 位置的验证失败。用户没有创建主目录/实例位置的权限

    安装weblogic12.1.3.0时,输入的安装命令是: 老是报这个错误. 百度半天好像没人报过这错……看来只有我这么粗心了…… 后来发现wls.rsp里面的Oracle_HOME指向目录错误,修改 ...

  10. Learning the Depths of Moving People by Watching Frozen

    基于双目的传统算法 对静止的物体, 在不同的 viewpoints 同一时刻进行拍摄, 根据拍摄到的结果, 使用三角测量算法计算出平面 2D 图像在 3D 图像中的坐标 单目 Ground Truth ...