要素の高さをReactCSSTransitionGroup
でアニメーション化しようとしているので、アニメーションは次のようにします。
http://jsfiddle.net/cherrry/hgk4Lme9/
問題は、要素の高さが常にわからないことです。そのため、scrollHeight
の間にclientHeight
、componentDidMount
などをハックして、node.style.height
またはスタイルシートにルールを追加
http://jsfiddle.net/cherrry/dz8uod7u/
アニメーションを残すと見栄えがよくなりますが、要素が入ると少し点滅し、スケーリングアニメーションが奇妙に見えます
これは、node.scrollHeight
に要求されたためにレンダリングがすぐに発生するためです。アニメーションを開始する前に、同じ情報を取得してCSSルールを挿入する方法はありますか?または私は逆に考える必要がありますか?
max-height
がheight
に近いか、それよりも小さく、コンポーネントの高さがそうでない場合、結果のアニメーション速度が非常に奇妙になるため、max-height
ソリューションにはあまり満足していません。大きく異なります。
最終的なソリューションが少し面倒になる可能性があると想像できましたが、それをMixinにすることは、どこにでも再利用できるほど十分だと思います
同じ問題があり、高さをアニメーション化するためのスタンドアロンコンポーネントを作成することになりました。
ここでデモを見ることができます: https://stanko.github.io/react-animate-height/
はるかに使いやすく、ライブラリ全体が非常に小さい(200行まで)
<AnimateHeight
duration={ 500 }
height={ 'auto' }
>
<h1>Your content goes here</h1>
<p>Put as many React or HTML components here.</p>
</AnimateHeight>
恥知らずな自己宣伝は申し訳ありませんが、アニメーション化するコンポーネントが複数ある場合は、時間を大幅に節約できると思います。
乾杯!
もう少し実験した後、高レベルのReactTransitionGroup
ではなく低レベルのAPI ReactCSSTransitionGroup
を使用して解決策を考え出しました
これが動作するソリューションを備えたJSFiddleです: http://jsfiddle.net/cherrry/0wgp34cr/
アニメーションの前に、3つのことを行っています。
display: none
で要素を非表示にし、.anim-enter
を追加して高さを0に設定します.anim-enter-active
のCSSルールを作成アニメーションを開始するには、次の2つのことを行います。
.anim-enter-active
を追加してアニメーションを開始しますJSFiddleの一部の数値とクラス名はハードコーディングされていましたが、「mixin」をReactCSSTransitionGroup
の代わりにReactクラスに変換するのは簡単です。
モジュールをインポートしたくない場合やqjueryを使用したくない場合は、React ref( https://reactjs.org/docs/refs-and-the-dom .html )
基本的には高さを取得し、その高さに成長し、自動に戻ります。戻る途中で高さを切り替え、次に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>
);
}
}