簡體   English   中英

在組件中的不同狀態之間進行平滑過渡

[英]React smooth transition between different states in a component

我有一個像這樣的簡單組件:

var component = React.createClass({
  render: function(){
      if (this.props.isCollapsed){
         return this.renderCollapsed();
      }
      return this.renderActive()
  },
  renderActive: function(){
    return (
      <div>
      ...
      </div>
    );
  },
  renderCollapsed: function(){
    return (
      <div>
      ...
      </div>
    );
  },
});

基本上,當屬性更改時,組件將顯示活動狀態或折疊狀態。

我在想的是,當財產發生變化時,即主動 - >崩潰,或者相反,我希望舊視圖“縮小”或“展開”平滑以顯示新視圖。 例如,如果它處於活動狀態 - >折疊,我希望活動UI縮小到折疊UI的大小,並平滑地顯示它。

我不知道如何達到這個效果。 請分享一些想法。 謝謝!

您可以改為,而不是有條件地渲染組件的兩個不同的最終狀態
在同一組件上切換類 您可以使用以下活動和折疊類:

例如:

.active{
  -webkit-transition: -webkit-transform .5s linear;  // transition of 
                                                     // 0.5 of a second
  height: 200px;
}

.collapsed{
  height: 0px;
}

查看此資源以獲取示例

這是一個最小的工作示例:

 const collapsible = ({active, toggle}) => <div> <button type="button" onClick={toggle}>Toggle</button> <div className={'collapsible' + (active? ' active': '')}> text </div> </div> const component = React.createClass({ getInitialState() { return {active: false} }, toggle() { this.setState({active: !this.state.active}) }, render() { return collapsible({active: this.state.active, toggle: this.toggle}) } }) ReactDOM.render(React.createElement(component), document.querySelector('#root')) 
 .collapsible { height: 1.5rem; transition: height 0.25s linear; background: #333; border-radius: 0.25rem } .collapsible.active { height: 7rem } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script> <div id="root"></div> 

CSS轉換可以平滑地“縮小”或“展開”視圖,這是通過更改CSS屬性觸發的。

要使用React控制CSS屬性,我們可以在render()反映屬性值或className狀態更改。

在此示例中, .active類影響height值,並由state.active控制。 響應狀態更改,React切換該類,並觸發CSS轉換。

要獲得更平滑的過渡,請參閱此文章

標准方法是使用react-transition-group中的 CSSTransitionGroup,這非常簡單。 使用CSSTransitionGroup包裝組件並在進入和離開時設置超時,如下所示:

<CSSTransitionGroup
      transitionName="example"
      transitionEnterTimeout={500}
      transitionLeaveTimeout={300}>
      {items}
</CSSTransitionGroup>

來自v1-stable文檔

“在這個組件中,當一個新項目被添加到CSSTransitionGroup時,它將獲得示例 - 輸入CSS類,並在下一個tick中添加example-enter-active CSS類。”

為CSS類添加樣式以獲取正確的動畫。

React docs中也有很好的解釋,請查看。

還有動畫的第三方組件。

這種情況的另一種方法可能是在動畫完成后改變狀態。 它的好處是你不僅可以應用轉換,而且可以應用你想要的任何動作(js動畫,smil等等),主要的是不要忘記調用結束回調;)

這是CodePen的工作示例

這是代碼示例:

const runTransition = (node, {property = 'opacity', from, to, duration = 600, post = ''}, end) => {
  const dif = to - from;
  const start = Date.now();

  const animate = ()=>{
    const step = Date.now() - start;
    if (step >= duration) {
      node.style[property] = to + post;
      return typeof end == 'function' && end();
    }

    const val =from + (dif * (step/duration));
    node.style[property] =  val + post;
    requestAnimationFrame(animate);
  }

  requestAnimationFrame(animate);

}

class Comp extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isCollapsed: false
    }

    this.onclick = (e)=>{
       this.hide(e.currentTarget,()=>{
         this.setState({isCollapsed: !this.state.isCollapsed})
       });
     };

    this.refF = (n)=>{
       n && this.show(n);
     };
  }

  render() {
    if (this.state.isCollapsed){
         return this.renderCollapsed();
      }
      return this.renderActive()
  }

  renderCollapsed() {
    return (
      <div 
        key='b'
        style={{opacity: 0}}
        ref={this.refF}
        className={`b`}
        onClick={this.onclick}>
          <h2>I'm Collapsed</h2>
      </div>
      )
  }

  renderActive() {
    return (
      <div 
        key='a'
        style={{opacity: 0}}
        ref={this.refF}
        className={`a`}
        onClick={this.onclick}>
          <h2>I'm Active</h2>
      </div>
      )
  }

  show(node, cb)  {
    runTransition(node, {from: 0, to: 1}, cb);
  }

  hide(node, cb) {
    runTransition(node, {from: 1, to: 0}, cb);
  }

}

ReactDOM.render(<Comp />, document.getElementById('content'));

當然,對於這種工作方法,你唯一的機會是繼續使用狀態,而不是Component的道具,如果你必須處理它們,你可以隨時在componentWillReceiveProps方法中設置它。

更新

使用更清晰的示例更新了Codepen鏈接 ,該示例顯示了此方法的優點。 轉換更改為javascript動畫,而不依賴於transitionend事件。

您可以添加描述活動狀態的類,即。 .active並在切換狀態時切換該類。

css看起來應該是這樣的:

.your-component-name{
  // inactive css styling here
}

.your-component-name.active {
  // active css styling here
}

由於您想為每個活動和折疊渲染兩個不同的組件,請將它們包裝在一個div中,該div通過CSS幫助控制高度。

render: function(){
var cls = this.props.isCollapsed() ? 'collapsed' : 'expanded';
return(
  <div className={cls + ' wrapper'}>
    {
      this.props.isCollapsed() ?
       this.renderCollapsed() :
       this.renderActive()
    }
  </div>
);
}

在你的CSS中:

.wrapper{
  transition: transform .5s linear;
}

.expanded{  
  height: 200px;
}

.collapsed{
  height: 20px;
}

在這里你有一個使用Velocity-React庫的Toggle反應組件,它非常適合為React uis中的過渡提供動畫:

import React, { Component } from 'react';
import { VelocityTransitionGroup } from 'velocity-react';

export default class ToggleContainer extends Component {
    constructor () {
        super();

        this.renderContent = this.renderContent.bind(this);
    }

    renderContent () {
        if (this.props.show) {
            return (
                <div className="toggle-container-container">
                    {this.props.children}
                </div>
            );
        }
        return null
    }

    render () {
        return (
            <div>
                <h2 className="toggle-container-title" onClick={this.props.toggle}>{this.props.title}</h2>
                <VelocityTransitionGroup component="div" enter="slideDown" leave="slideUp">
                    {this.renderContent()}
                </VelocityTransitionGroup>
            </div>
        );
    }

};

ToggleContainer.propTypes = {
    show: React.PropTypes.bool,
    title: React.PropTypes.string.isRequired,
    toggle: React.PropTypes.func.isRequired,
};

希望能幫助到你!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM