React / CSS-当宽度为自动时,内容更改后,动画按钮的宽度将重新调整

时间:2018-08-17 10:54:14

标签: javascript html css reactjs css-transitions

我有一个表示按钮的react组件,该按钮根据某些props更改内容和颜色。如果表单组件包含此按钮并提交,则该按钮将更改其内容和颜色。效果很好。

现在,我需要一个动画(CSS过渡)来改变按钮的内容。 为不同的状态设置一个明确的width是不可行的,因为该应用程序是多语言的。使用max-width时,动画仅在按钮扩展时起作用,而在按钮减小时不起作用。

这是一个带有按钮组件的代码段,它每秒都会更改状态。就像在实际组件中一样,此人使用引导btn类:

class Button extends React.Component {
  constructor(props) {
    super(props);
    this.state = {status: 0};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  tick() {
    let status = this.state.status;
    status++;
    if(status >= 2) {
      status = 0;
    }
    this.setState({
      status: status
    });
  }

  render() {
    const btnClass = this.state.status ? 'primary' : 'secondary';
    
    return (
      <button className={`btn btn-${btnClass}`} type='button'>
        {this.state.status ? this.props.large : this.props.short}
      </button>
    );
  }
}

// Render it
ReactDOM.render(
  <Button large='This is a long button you can click on!' short='short'/>,
  document.getElementById('react')
);
.btn {
    -webkit-transition: width 1s; /* Safari */
    transition: max-width 1s;
    width: auto;
}

.btn-primary {
  max-width: 300px;
}

.btn-secondary {
  max-width: 50px;
}
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

如何获得变化的width的动画(当按钮再次变小时)?

请考虑答案并不仅限于CSS。我想到了react组件会计算它的宽度,然后将其设置在componentWillMount函数中,但这也不起作用...

2 个答案:

答案 0 :(得分:3)

尝试将width: 100%设置为.btn类。为max-width属性设置动画没有错。当文本从小文本变为大文本时,就会出现问题,浏览器将不得不重新计算auto作为width属性值的含义。看来100%的工作方式不同。

class Button extends React.Component {
  constructor(props) {
    super(props);
    this.state = {status: 0};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  tick() {
    let status = this.state.status;
    status++;
    if(status >= 2) {
      status = 0;
    }
    this.setState({
      status: status
    });
  }

  render() {
    const btnClass = this.state.status ? 'primary' : 'secondary';
    
    return (
      <button className={`btn btn-${btnClass}`} type='button'>
        {this.state.status ? this.props.large : this.props.short}
      </button>
    );
  }
}

// Render it
ReactDOM.render(
  <Button large='This is a long button you can click on!' short='short'/>,
  document.getElementById('react')
);
.btn {
    -webkit-transition: width 1s; /* Safari */
    transition: max-width 1s;
    width: 100%;
}

.btn-primary {
  max-width: 300px;
}

.btn-secondary {
  max-width: 50px;
}
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

答案 1 :(得分:1)

我有解决办法。将最小宽度添加到您的CSS类并按如下所示进行转换。

在上行动画。在下降的过程中制作动画。

class Button extends React.Component {
  constructor(props) {
    super(props);
    this.state = {status: 0};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  tick() {
    let status = this.state.status;
    status++;
    if(status >= 2) {
      status = 0;
    }
    this.setState({
      status: status
    });
  }

  render() {
    const btnClass = this.state.status ? 'primary' : 'secondary';
    
    return (
      <button className={`btn btn-${btnClass}`} type='button'>
        {this.state.status ? this.props.large : this.props.short}
      </button>
    );
  }
}

// Render it
ReactDOM.render(
  <Button large='This is a long button you can click on!' short='short'/>,
  document.getElementById('react')
);
.btn {
    -webkit-transition: width 1s; /* Safari */
     transition: max-width 1s, min-width 1s;
     width: auto;
}

.btn-primary {
  max-width: 330px;
  min-width: 230px;
}

.btn-secondary {
  max-width: 60px;
  min-width: 40px;
  text-align: left;
}
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">