zoukankan      html  css  js  c++  java
  • 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可编程性最大,最灵活,可以适合复杂的动画场景或者承受复杂的交互场景。

    安装

    npm install css3transform-react
    

    API

    //set "translateX", "translateY", "translateZ", "scaleX", "scaleY", "scaleZ", "rotateX", "rotateY", "rotateZ", "skewX", "skewY", "originX", "originY", "originZ"
    render() {
        return (
            <Transform
              translateX={100}
              scaleX={0.5}
              originX={0.5}>
              <div>sth</div>
            </Transform>
        );
    }
    
    // you can also use other porps, such as "className" or "style"
    render() {
        return (
            <Transform
              translateX={100}
              className="ani"
              style={{ '100px', background: 'red'}}
              <div>sth</div>
            </Transform>
        );
    }
    

    通过上面的声明,就可以设置或者读取"translateX", "translateY", "translateZ", "scaleX", "scaleY", "scaleZ", "rotateX", "rotateY", "rotateZ", "skewX", "skewY", "originX", "originY", "originZ"!

    方便吧!

    使用姿势

    import React, { Component } from 'react';
    import { render } from 'react-dom';
    
    import Transform from '../../transform.react.js';
    
    class Root extends Component {
    
      constructor(props, context) {
        super(props, context);
    
        this.state = {
          el1: {rotateZ: 0},
          el2: {rotateY: 0}
        };
    
        this.animate = this.animate.bind(this);
      }
    
      animate() {
        this.setState({
          el1: {rotateZ: this.state.el1.rotateZ + 1},
          el2: {rotateY: this.state.el2.rotateY + 1}
        }, () => {
          requestAnimationFrame(this.animate);
        });
    
      }
    
      componentDidMount() {
        setTimeout(this.animate, 500);
      }
    
      render() {
        return (
          <div>
            <Transform rotateZ={this.state.el1.rotateZ} className="test" style={{'backgroundColor': 'green'}}>
              transformjs
            </Transform>
    
            <Transform rotateY={this.state.el2.rotateY} className="test" style={{'backgroundColor': 'red', 'left': '200px'}}>
              transformjs
            </Transform>
    
          </div>
        );
      }
    }
    
    render(
    	<Root />,
    	document.getElementById('root')
    );
    

    更加复杂的详细的使用代码可以看这里: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的方式对比。就是下面这种传统的方式:

    var element1 = document.querySelector("#test1");
    Transform(element1);
    ...
    ...
    function animate() {
        element1.rotateZ++;
        ...
        requestAnimationFrame(animate);
    }
    
    animate();
    

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

    react:

    传统方式:

    • react在8739秒内CPU耗时花费了近似1686ms
    • 传统方式在9254ms秒内CPU耗时花费近似700ms

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

    就是它了。

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

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

    开始使用吧

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

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

  • 相关阅读:
    Hologres如何支持亿级用户UV计算
    飞猪基于 Serverless 的云+端实践与思考
    高德打车构建可观测性系统实践
    程序员写好技术文章的几点小技巧
    配置审计(Config)变配报警设置
    进入中国内地第31年的麦当劳 ,为什么还能不断吸引新消费人群?
    OceanBase再破纪录!核心成员陈萌萌:坚持HTAP就是坚持我们做数据库的初心
    找出有序数组中缺失的数字
    删除值重复的结点
    想交链表----若有缘 必相见
  • 原文地址:https://www.cnblogs.com/iamzhanglei/p/6196328.html
Copyright © 2011-2022 走看看