react动画难写?试试react版transformjs

前端之家收集整理的这篇文章主要介绍了react动画难写?试试react版transformjs前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

简介

transformjs在非react领域用得风生水起,那么react技术栈的同学能用上吗?答案是可以的。junexie童鞋已经造了个react版本

动画实现方式

传统 web 动画的两种方式

  1. 纯粹的CSS3 :如:transition/animation+transform(大名鼎鼎的animate.css)

  2. JS + CSS3 transition或者animation:这里第一种一样,只是通过js里add class和remove class去增加或者移除对应的动画

  3. 纯粹JS控制时间轴:第一和第二种都是自带时间轴,使用 setInterval / setTimeout / requestAnimationFrame 不断地修改 DOM 的 style 属性产生动画

对应在react中

使用CSS3

  • 使用 ReactCSSTransitionGroup 来实现

  • 相关动画的class都有对应的state,修改state相当于增加或者移除class,也就相当于js里add class和remove class去增加或者移除对应的动画

    纯粹JS控制时间轴

  • 仍然使用 setInterval / setTimeout / requestAnimationFrame,修改某个 state 值,然后映射到 component 的 style 上。

这里很明显,方案1和方案2可应对简单场景(如没有prop change 回调等),方案3可编程性最大,最灵活,可以适合复杂的动画场景或者承受复杂的交互场景。

安装

  1. npm install css3transform-react

API

  1. //set "translateX","translateY","translateZ","scaleX","scaleY","scaleZ","rotateX","rotateY","rotateZ","skewX","skewY","originX","originY","originZ"
  2. render() {
  3. return (
  4. <Transform
  5. translateX={100}
  6. scaleX={0.5}
  7. originX={0.5}>
  8. <div>sth</div>
  9. </Transform>
  10. );
  11. }
  12.  
  13. // you can also use other porps,such as "className" or "style"
  14. render() {
  15. return (
  16. <Transform
  17. translateX={100}
  18. className="ani"
  19. style={{width: '100px',background: 'red'}}
  20. <div>sth</div>
  21. </Transform>
  22. );
  23. }

通过上面的声明,就可以设置或者读取"translateX","originZ"!

方便吧!

使用姿势

  1. import React,{ Component } from 'react';
  2. import { render } from 'react-dom';
  3.  
  4. import Transform from '../../transform.react.js';
  5.  
  6. class Root extends Component {
  7.  
  8. constructor(props,context) {
  9. super(props,context);
  10.  
  11. this.state = {
  12. el1: {rotateZ: 0},el2: {rotateY: 0}
  13. };
  14.  
  15. this.animate = this.animate.bind(this);
  16. }
  17.  
  18. animate() {
  19. this.setState({
  20. el1: {rotateZ: this.state.el1.rotateZ + 1},el2: {rotateY: this.state.el2.rotateY + 1}
  21. },() => {
  22. requestAnimationFrame(this.animate);
  23. });
  24.  
  25. }
  26.  
  27. componentDidMount() {
  28. setTimeout(this.animate,500);
  29. }
  30.  
  31. render() {
  32. return (
  33. <div>
  34. <Transform rotateZ={this.state.el1.rotateZ} className="test" style={{'backgroundColor': 'green'}}>
  35. transformjs
  36. </Transform>
  37.  
  38. <Transform rotateY={this.state.el2.rotateY} className="test" style={{'backgroundColor': 'red','left': '200px'}}>
  39. transformjs
  40. </Transform>
  41.  
  42. </div>
  43. );
  44. }
  45. }
  46.  
  47. render(
  48. <Root />,document.getElementById('root')
  49. );

更加复杂的详细的使用代码可以看这里:https://github.com/AlloyTeam/AlloyTouch/blob/master/transformjs/react/example/src/index.jsx

在线演示

http://alloyteam.github.io/AlloyTouch/transformjs/react/example/

性能对比

因为react版本会有diff过程,然后apply diff to dom的过程,state改变不会整个innerHTML全部替换,所以对浏览器渲染来说还是很便宜,但是在js里diff的过程的耗时还是需要去profiles一把,如果耗时严重,不在webworker里跑还是会卡住UI线程导致卡顿,交互延缓等。所以要看一看cpu的耗时还是很有必要的。
主要是那上面的演示和传统的直接操作dom的方式对比。就是下面这种传统的方式:

  1. var element1 = document.querySelector("#test1");
  2. Transform(element1);
  3. ...
  4. ...
  5. function animate() {
  6. element1.rotateZ++;
  7. ...
  8. requestAnimationFrame(animate);
  9. }
  10.  
  11. animate();

对两种方式使用chrome profiles了一把。
先看总耗时对比

react:

传统方式:

  • react在8739秒内cpu耗时花费了近似1686ms

  • 传统方式在9254ms秒内cpu耗时花费近似700ms

在不进行profiles就能想象到react是一定会更慢一些,因为state的改变要走把react生命周期走一遍,但是可以看到react的耗时还是在可以接受的范围。但是,我们还是希望找到拖慢的函数来。
那么在使用transformjs react版本中,哪个函数拖了后腿?展开profiles tree可以看到:

就是它了。

  1. /**
  2. * Reconciles the properties by detecting differences in property values and
  3. * updating the DOM as necessary. This function is probably the single most
  4. * critical path for performance optimization.
  5. *
  6. * TODO: Benchmark whether checking for changed values in memory actually
  7. * improves performance (especially statically positioned elements).
  8. * TODO: Benchmark the effects of putting this at the top since 99% of props
  9. * do not change for a given reconciliation.
  10. * TODO: Benchmark areas that can be improved with caching.
  11. *
  12. * @private
  13. * @param {object} lastProps
  14. * @param {object} nextProps
  15. * @param {?DOMElement} node
  16. */
  17. _updateDOMProperties: function (lastProps,nextProps,transaction) {

打开对应的代码可以看到。注释里已经写了这是优化重点。

开始使用吧

官方网站:http://alloyteam.github.io/AlloyTouch/transformjs/

Github地址:https://github.com/AlloyTeam/AlloyTouch/tree/master/transformjs
任何问题和意见欢迎new issue给我们。

猜你在找的React相关文章