Javascript 在组件的不同状态之间平滑过渡
我有一个简单的组件,如下所示:Javascript 在组件的不同状态之间平滑过渡,javascript,css,reactjs,css-transitions,Javascript,Css,Reactjs,Css Transitions,我有一个简单的组件,如下所示: .your-component-name{ // inactive css styling here } .your-component-name.active { // active css styling here } var component=React.createClass({ render:function(){ 如果(此.props.isCollapsed){ 返回此.renderCollapsed(); } 返回这个。renderAc
.your-component-name{
// inactive css styling here
}
.your-component-name.active {
// active css styling here
}
var component=React.createClass({
render:function(){
如果(此.props.isCollapsed){
返回此.renderCollapsed();
}
返回这个。renderActive()
},
renderActive:function(){
返回(
...
);
},
renderCollapsed:function(){
返回(
...
);
},
});
基本上,当属性更改时,组件将显示活动状态或折叠状态
我想的是,当属性发生更改时,即active->collapse,或相反,我希望旧视图“收缩”或“展开”平滑地显示新视图。例如,如果它是活动的->折叠,我希望活动的UI缩小到折叠UI的大小,并平滑地显示它
我不知道如何达到这个效果。请分享一些想法。谢谢
而不是有条件地呈现
组件,您可以在同一服务器上切换类
组成部分。可以按如下方式创建活动类和折叠类:
例如:
.active{
-webkit转换:-webkit转换.5s线性;//的转换
//0.5秒
高度:200px;
}
.崩溃{
高度:0px;
}
查看示例您可以添加一个描述活动状态的类,即
.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”;
返回(
{
this.props.isCollapsed()?
此.renderCollapsed():
这个
}
);
}
在CSS中:
.wrapper{
过渡:变换。5s线性;
}
.扩大{
高度:200px;
}
.崩溃{
高度:20px;
}
以下是一个简单的工作示例:
常量可折叠=({active,toggle})=>
切换
文本
const component=React.createClass({
getInitialState(){
返回{active:false}
},
切换(){
this.setState({active:!this.state.active})
},
render(){
返回可折叠({active:this.state.active,toggle:this.toggle})
}
})
ReactDOM.render(React.createElement(组件)、document.querySelector('#root'))
。可折叠{
高度:1.5雷姆;
过渡段:高度0.25s线性;
背景:#333;
边界半径:0.25雷姆
}
.可折叠的{
身高:7雷姆
}
解决这种情况的另一种方法可能是在动画完成后更改状态。它的好处是,您不仅可以应用转换,还可以应用任何您想要的操作(js动画、smil等),主要的是不要忘记调用结束回调;) 下面是一个工作示例 下面是代码示例:
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'));
const runTransition=(节点,{property='opacity',from,to,duration=600,post=''},end)=>{
const dif=到-从;
const start=Date.now();
常量动画=()=>{
const step=Date.now()-开始;
如果(步骤>=持续时间){
node.style[property]=to+post;
返回typeof end=='function'&&end();
}
const val=from+(dif*(步长/持续时间));
node.style[property]=val+post;
请求动画帧(动画);
}
请求动画帧(动画);
}
类Comp.Component{
建造师(道具){
超级(道具);
此.state={
isCollapsed:错误
}
this.onclick=(e)=>{
this.hide(例如currentTarget,()=>{
this.setState({isCollapsed:!this.state.isCollapsed})
});
};
this.refF=(n)=>{
n&&this.show(n);
};
}
render(){
if(this.state.isCollapsed){
返回此.renderCollapsed();
}
返回这个。renderActive()
}
renderCollapsed(){
返回(
我崩溃了
)
}
渲染的{
返回(
我很活跃
)
}
显示(节点,cb){
runTransition(节点,{from:0,to:1},cb);
}
隐藏(节点,cb){
runTransition(节点,{from:1,to:0},cb);
}
}
ReactDOM.render(,document.getElementById('content'));
当然,对于这种方法,您唯一的机会是依赖于状态,而不是组件的道具,如果您必须处理它们,您可以始终在componentWillReceiveProps方法中设置这些道具
更新
更新了更清晰的示例,显示了此方法的好处。转换更改为javascript动画,不依赖于transitionend事件 标准方法是使用CSSTransitionGroup from,这非常简单。使用
CSSTransitionGroup
包装组件,并在enter和leave上设置超时,如下所示:
<CSSTransitionGroup
transitionName="example"
transitionEnterTimeout={500}
transitionLeaveTimeout={300}>
{items}
</CSSTransitionGroup>
{items}
从:
“在此组件中,将新项添加到CSSTransitionGroup时
将获得示例enter CSS类和示例enter active CSS
在下一个勾号中添加了类。“
为CSS类添加样式以获得正确的动画
里面也有很好的解释,看看吧
还有用于动画的第三方组件。这里有一个使用Velocity react库的Toggle react组件,非常适合在react UI中为过渡提供动画:
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,
};
import React,{Component}来自'React';
从“velocity react”导入{VelocityTransitionGroup};
导出默认类ToggleContainer扩展组件{
构造函数(){
超级();
this.renderContent=this.renderContent.bind(this);
}
renderContent(){
如果(这个.道具.表演){
返回(
{th