react动画难写?试试react版transformjs分分快三计划

作者:分分快三计划

使用姿势

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')
);

更加复杂的详细的使用代码可以看这里:

通过npm安装

npm install omi-transform

简介

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

演示

性能对比

因为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:
分分快三计划 1

传统方式:
分分快三计划 2

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

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

分分快三计划 3

就是它了。

/**
       * 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) {

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

写在前面

Omi框架正式发布了omi-transform作为Omi组件化开发特效运动解决方案,让你轻松在Omi项目里快速简便支持CSS3 Transform设置。先说说 transform.js (npm上的名字是 css3transform)。transform.js作为移动Web特效解决方案,在手Q兴趣部落、日迹、QQ群、QQ附近等项目中广泛使用,以激进的修改DOM属性为代价,带来极为便利的可编程性。

你可以通过快速了解它。

上面官网的例子都是原声js的,transformjs也拥有react版本,你也可以在react中以声明式的方式使用transformjs:

render() {
    return (
        <Transform
          translateX={100}
          scaleX={0.5}
          originX={0.5}>
          <div>sth</div>
        </Transform>
    );
}

在线演示

性能对比

因为react版本会有diff过程,然后apply diff to dom的过程,state改变不会整个innerHTML全部替换,所以对浏览器渲染来说还是很便宜,但是在js里diff的过程的耗时还是需要去profiles一把,如果耗时严重,不在webworker里跑还是会卡住UI线程导致卡顿,交互延缓等。所以要看一看CPU的耗时还是很有必要的。

下面数据是对比omi-transform和react-transform,两种方式使用chrome profiles了一把。

先看总耗时对比

react-transform:
分分快三计划 4

omi-transform:
分分快三计划 5

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

在不进行profiles就能想象到react是一定会更慢一些,因为state的改变要走把react生命周期走一遍,但是可以看到react的耗时还是在可以接受的范围,没有慢到难以接受。

而Omi的方式则和传统的原生js的耗时一模一样。以为运动过程不进行DOMI Diff!!

慢着?不进行Diff?意思就是组件不进行update?
意思就是万一组件update,所有运动的状态都会丢失?Omi怎么解决这个问题?

开始使用吧

官方网站:

Github地址:
任何问题和意见欢迎new issue给我们。

使用

import Omi from 'omi';
import OmiTransform from '../../omi-transform.js';

OmiTransform.init();

class App extends Omi.Component {
    constructor(data) {
        super(data);
    }

    installed(){
        setInterval(function(){
            this.refs.test.rotateZ  = 0.1;
        }.bind(this));
    }

    render() {
        return  `
            <div omi-transform class="test" ref="test" rotateZ="45" translateX="100" perspective="400">
                omi-transform
            </div>

        `;
    }
}

Omi.render(new App(),"#container");
  • 在需要使用transformjs的DOM上标记 omi-transform 和 ref="xxx"
  • 在组件函数里便可以使用 this.refs.xxx 来读取或者设置 css transform属性
  • this.refs.xxx 支持 "translateX", "translateY", "translateZ", "scaleX", "scaleY", "scaleZ", "rotateX", "rotateY", "rotateZ", "skewX", "skewY", "originX", "originY", "originZ", "perspective"这些属性设置和读取
  • 没有标记perspective的话代码没有透视投影

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={{width: '100px', background: 'red'}}
          <div>sth</div>
        </Transform>
    );
}

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

方便吧!

状态保存

组件里的某个DOM在运动过程中,可能会由于其他逻辑,进行update。有可能是用户交互,有可能是数据返回的回调。所以,update前后,DOM的状态的保留显得尤其重要,不然的话就会有闪烁、跳跃的效果或者其他显示逻辑错误。

    ...
    constructor(data) {
        super(data);
        //初始状态
        this.rotateZ  = 45;
    }

    installed(){
        setInterval(() =>{
            //sync for update 记录同步到this.rotateZ
            this.rotateZ = this.refs.test.rotateZ  = 0.1;
        });
    }

    render() {
        //通过 ${this.rotateZ} 设置rotateZ
        return  `
            <div omi-transform class="test" ref="test" rotateZ="${this.rotateZ}" translateX="100" perspective="400" >
                omi-transform
            </div>

        `;
    }
    ...

react动画难写?试试react版transformjs分分快三计划。上面的所有例子和代码可以在这里找到。

动画实现方式

传统 web 动画的两种方式

  1. 纯粹的CSS3 :如:transition/animation transform(大名鼎鼎的animate.css)
  2. JS CSS3 transition或者animation:这里第一种一样,只是通过js里add class和remove class去增加或者移除对应的动画
  3. react动画难写?试试react版transformjs分分快三计划。纯粹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可编程性最大,最灵活,可以适合复杂的动画场景或者承受复杂的交互场景。

react动画难写?试试react版transformjs分分快三计划。Omi相关

  • Omi官网omijs.org
  • Omi的Github地址
  • 如果想体验一下Omi框架,可以访问 Omi Playground
  • 如果想使用Omi框架或者开发完善Omi框架,可以访问 Omi使用文档
  • 如果你想获得更佳的阅读体验,可以访问 Docs Website
  • 如果你懒得搭建项目脚手架,可以试试 omi-cli
  • 如果你有Omi相关的问题可以 New issue
  • 如果想更加方便的交流关于Omi的一切可以加入QQ的Omi交流群(256426170)

分分快三计划 6

安装

npm install css3transform-react

3分钟掌握omi-transform

原文链接 - https://github.com/AlloyTeam/omi/tree/master/tutorial

本文由分分快三计划发布,转载请注明来源

关键词: 分分快三计划 HTML5