Reactjs 如何在React with ReactCSTransanitionGroup中设置元素高度的动画?
我正在尝试使用Reactjs 如何在React with ReactCSTransanitionGroup中设置元素高度的动画?,reactjs,actualheight,reactcsstransitiongroup,Reactjs,Actualheight,Reactcsstransitiongroup,我正在尝试使用reactcstransitiongroup设置元素高度的动画, 这就是我想要动画的样子: 问题是我并不总是知道元素的高度, 因此,我尝试在组件安装期间破解滚动高度,clientHeight或类似的东西,并尝试设置节点.style.height或向样式表添加规则 离开动画看起来不错,但是当元素进入时,它会闪烁一点,缩放动画看起来很奇怪 这应该是因为询问节点。scrollHeight导致渲染立即发生,所以在动画开始之前,是否仍然可以获得相同的信息并注入css规则?或者我应该换个角
reactcstransitiongroup
设置元素高度的动画,
这就是我想要动画的样子:
问题是我并不总是知道元素的高度,
因此,我尝试在组件安装期间破解滚动高度
,clientHeight
或类似的东西,并尝试设置节点.style.height
或向样式表添加规则
离开动画看起来不错,但是当元素进入时,它会闪烁一点,缩放动画看起来很奇怪
这应该是因为询问节点。scrollHeight
导致渲染立即发生,所以在动画开始之前,是否仍然可以获得相同的信息并注入css规则?或者我应该换个角度思考
我对max height
解决方案不太满意,因为当max height
不接近或小于height
时,生成的动画速度会非常奇怪,而且我的组件的高度变化很大
我可以想象最终的解决方案会有点混乱,
但是我认为把它变成一个Mixin就足够好了,可以在任何地方重用它经过更多的实验,我想出了一个解决方案,使用低级APIReactTransitionGroup
而不是高级ReactCSTranslationGroup
下面是JSFIDLE,它提供了一个有效的解决方案:
在制作动画之前,它要做3件事:
获取计算的高度、填充和边距
使用display:none
隐藏元素并添加。anim enter
将高度设置为0
为创建css规则。动画输入active
要开始动画,它需要做两件事:
取消隐藏元素
添加.anim输入active
以启动动画
JSFIDLE中的一些数字和类名是硬编码的,但是将“mixin”转换为React类来代替React CSTransanizingGroup应该很容易,因为我遇到了同样的问题,最后编写了一个独立的组件来设置高度动画
您可以在此处看到演示:
它更易于使用,而且整个库非常小(约200行)
你的内容放在这里
在此处放置尽可能多的React或HTML组件
很抱歉进行无耻的自我宣传,但我认为如果你有多个组件需要制作动画,那么它可以为你节省很多时间
干杯 如果您不想导入模块或使用qjuery,这里有一个使用React ref()的模板
基本上你得到了它的高度,增长到那个高度,切换回自动。在返回的过程中,切换到当前高度,然后返回到0
class CollapsibleSectionBlock extends React.Component {
constructor(props) {
super(props);
this.state = {
showContent: false,
height: "0px",
myRef: null,
};
}
componentDidUpdate = (prevProps, prevState) => {
if (prevState.height === "auto" && this.state.height !== "auto") {
setTimeout(() => this.setState({ height: "0px" }), 1);
}
}
setInnerRef = (ref) => this.setState({ myRef: ref });
toggleOpenClose = () => this.setState({
showContent: !this.state.showContent,
height: this.state.myRef.scrollHeight,
});
updateAfterTransition = () => {
if (this.state.showContent) {
this.setState({ height: "auto" });
}
};
render() {
const { title, children } = this.props;
return (
<div>
<h2 onClick={() => this.toggleOpenClose()}>
Example
</h2>
<div
ref={this.setInnerRef}
onTransitionEnd={() => this.updateAfterTransition()}
style={{
height: this.state.height,
overflow: "hidden",
transition: "height 250ms linear 0s",
}}
>
{children}
</div>
</div>
);
}
类可折叠分段块扩展React.Component{
建造师(道具){
超级(道具);
此.state={
showContent:false,
高度:“0px”,
myRef:null,
};
}
componentDidUpdate=(prevProps,prevState)=>{
如果(prevState.height==“自动”&&this.state.height!==“自动”){
setTimeout(()=>this.setState({height:“0px”}),1);
}
}
setInnerRef=(ref)=>this.setState({myRef:ref});
toggleOpenClose=()=>this.setState({
showContent:!this.state.showContent,
高度:this.state.myRef.scrollHeight,
});
updateAfterTransition=()=>{
if(this.state.showContent){
this.setState({height:“auto”});
}
};
render(){
const{title,children}=this.props;
返回(
this.toggleOpenClose()}>
例子
this.updateAfterTransition()}
风格={{
高度:this.state.height,
溢出:“隐藏”,
过渡:“高度250ms线性0s”,
}}
>
{儿童}
);
}
}嗯,这并不是你解释过的无耻的自我推销。好的。但是回答老问题时要小心。谢谢,我不知道这是个老问题,我的错!我喜欢react动画高度,但如何在宽度上获得相同的效果。这在使用react样式编程时不起作用,即{This.state.show?:null}
当然不起作用。使用此选项:
animatehight负责可访问性并隐藏内容。
class CollapsibleSectionBlock extends React.Component {
constructor(props) {
super(props);
this.state = {
showContent: false,
height: "0px",
myRef: null,
};
}
componentDidUpdate = (prevProps, prevState) => {
if (prevState.height === "auto" && this.state.height !== "auto") {
setTimeout(() => this.setState({ height: "0px" }), 1);
}
}
setInnerRef = (ref) => this.setState({ myRef: ref });
toggleOpenClose = () => this.setState({
showContent: !this.state.showContent,
height: this.state.myRef.scrollHeight,
});
updateAfterTransition = () => {
if (this.state.showContent) {
this.setState({ height: "auto" });
}
};
render() {
const { title, children } = this.props;
return (
<div>
<h2 onClick={() => this.toggleOpenClose()}>
Example
</h2>
<div
ref={this.setInnerRef}
onTransitionEnd={() => this.updateAfterTransition()}
style={{
height: this.state.height,
overflow: "hidden",
transition: "height 250ms linear 0s",
}}
>
{children}
</div>
</div>
);
}