react-transition-group 卡片翻转动画
react-transition-group card flip animation
我是 react-transition-group 的新手,我正在尝试制作卡片翻转动画。我能够让第一面翻转,但它不喜欢留在背面的想法。知道我在这里做错了什么吗?
import {useState} from "react";
import {CSSTransition} from "react-transition-group";
import "./styles.css";
export default function App() {
const [flipped, setFlipped] = useState(false);
return (
<div className="card-container">
<button
className="card-button"
onClick={() => setFlipped(!flipped)}
>
<CSSTransition
in={flipped}
timeout={1000}
classNames="front-face-transition"
>
<div className="card-front">
<p>front-side</p>
</div>
</CSSTransition>
<CSSTransition
in={!flipped}
timeout={1000}
classNames="back-face-transition"
>
<div className="card-back">
<p>back-side</p>
</div>
</CSSTransition>
</button>
</div>
);
}
.App {
font-family: sans-serif;
text-align: center;
}
.card-container {
width: 250px;
height: 400px;
padding: 0;
margin: 0;
}
.card-container .card-button {
padding: 0;
margin: 0;
border: none;
cursor: pointer;
width: 100%;
height: 100%;
position: relative;
}
.front-face-transition-enter {
transform-style: preserve-3d;
transition: all 1000ms ease;
transform: rotateY(0deg);
}
.front-face-transition-enter-active {
transform: rotateY(180deg);
}
.front-face-transition-enter-done {
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.back-face-transition-enter {
transform-style: preserve-3d;
transition: all 1000ms ease;
transform: rotateY(0deg);
display: block;
}
.back-face-transition-enter-active {
transform: rotateY(-180deg);
display: block;
}
.back-face-transition-enter-done {
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.card-front {
display: none;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
此外,这里有一个有效的 codesandbox link 代码以防万一也有帮助。
这里有很多东西要打开。没有一个错误导致您出现问题,但有很多小错误。我会尽力解决这些问题。在大多数情况下,你的 React 是正确的,但 CSS 是你遇到麻烦的地方。
tl;dr:这是一个有效的 code sandbox
- 您需要在
active
class 上放置转换。这是约定俗成的,但对于您的特定示例,它们可能是卡片元素上的永久属性。
- transform-style保留 3d 需要在 3d 元素的父级上
- 如果您希望页面加载时正面朝前,那么您的
flipped
逻辑就是倒退的
- 你的正面有
display: none
,这意味着它根本不可见。
- 如果您希望保持变换(180 度转弯),则需要指定
exit-done
和 enter-done
。将这些规则设置为与 active
class 具有相同的变换值,这将使动画结束后的一侧“保持原样”。
- 背面可见性可以是面部元素的永久属性
- 背面的显示块什么也没做——它已经是块了,因为它是一个 div 元素。我想你是想把它放在 card-front 规则中。
- 需要在父元素上设置
perspective
属性 才能看到真正的 3d 效果。这是一个像素值,表示观看者与 z space. 中的元素的距离
- 需要对卡片布局进行更多调整才能使其正确。我在下面添加了我的基本样式。
- 3d 元素容器的背景(你的例子中的按钮)应该有
transparent
的背景,否则卡片在 3d 中移动时会切穿背景 space。
- 在以这种方式旋转的元素上设置一个明确的背景是个好主意,这样动画会更流畅。
我想就这些了。
代码
import { useState } from "react";
import { CSSTransition } from "react-transition-group";
import "./styles.css";
export default function App() {
const [flipped, setFlipped] = useState(false);
return (
<div className="card-container">
<button className="card-button" onClick={() => setFlipped(!flipped)}>
<CSSTransition
in={!flipped}
timeout={1000}
classNames="front-face-transition"
>
<div className="card-front">
<p>front-side</p>
</div>
</CSSTransition>
<CSSTransition
in={flipped}
timeout={1000}
classNames="back-face-transition"
>
<div className="card-back">
<p>back-side</p>
</div>
</CSSTransition>
</button>
</div>
);
}
body {
background-color: darkgray;
}
.App {
font-family: sans-serif;
text-align: center;
}
.card-container {
width: 250px;
height: 400px;
padding: 0;
margin: 0;
}
.card-container .card-button {
padding: 0;
margin: 0;
border: none;
cursor: pointer;
width: 100%;
height: 100%;
position: relative;
background: transparent;
transform-style: preserve-3d;
perspective: 5000px;
}
.card-front,
.card-back {
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 100%;
}
.card-front {
background: beige;
position: absolute;
top: 0;
left: 0;
}
.card-back {
background: aliceblue;
}
.front-face-transition-enter {
transform: rotateY(180deg);
}
.front-face-transition-enter-active {
transition: all 1000ms ease;
transform: rotateY(0deg);
}
.front-face-transition-enter-done {
transform: rotateY(0deg);
}
.front-face-transition-exit {
transform: rotateY(0deg);
}
.front-face-transition-exit-active {
transform: rotateY(180deg);
transition: all 1000ms ease;
}
.front-face-transition-exit-done {
transform: rotateY(180deg);
}
.back-face-transition-enter {
transform: rotateY(-180deg);
}
.back-face-transition-enter-active {
transform: rotateY(0deg);
transition: all 1000ms ease;
}
.back-face-transition-enter-done {
transform: rotateY(0deg);
}
.back-face-transition-exit {
transform: rotateY(0deg);
}
.back-face-transition-exit-active {
transform: rotateY(-180deg);
transition: all 1000ms ease;
}
.back-face-transition-exit-done {
transform: rotateY(-180deg);
}
总的来说,您的代码可能比较干燥。寻找相似元素的共享样式并将它们组合在一起以避免不必要的麻烦。我在代码示例中留下了一些优化方法,但是例如您可以看到 .front-face-transition-exit-done
和 .front-face-transition-enter
具有相同的规则,将它们放在一起!
祝CSS过渡顺利,如果您有任何问题,请告诉我。
我是 react-transition-group 的新手,我正在尝试制作卡片翻转动画。我能够让第一面翻转,但它不喜欢留在背面的想法。知道我在这里做错了什么吗?
import {useState} from "react";
import {CSSTransition} from "react-transition-group";
import "./styles.css";
export default function App() {
const [flipped, setFlipped] = useState(false);
return (
<div className="card-container">
<button
className="card-button"
onClick={() => setFlipped(!flipped)}
>
<CSSTransition
in={flipped}
timeout={1000}
classNames="front-face-transition"
>
<div className="card-front">
<p>front-side</p>
</div>
</CSSTransition>
<CSSTransition
in={!flipped}
timeout={1000}
classNames="back-face-transition"
>
<div className="card-back">
<p>back-side</p>
</div>
</CSSTransition>
</button>
</div>
);
}
.App {
font-family: sans-serif;
text-align: center;
}
.card-container {
width: 250px;
height: 400px;
padding: 0;
margin: 0;
}
.card-container .card-button {
padding: 0;
margin: 0;
border: none;
cursor: pointer;
width: 100%;
height: 100%;
position: relative;
}
.front-face-transition-enter {
transform-style: preserve-3d;
transition: all 1000ms ease;
transform: rotateY(0deg);
}
.front-face-transition-enter-active {
transform: rotateY(180deg);
}
.front-face-transition-enter-done {
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.back-face-transition-enter {
transform-style: preserve-3d;
transition: all 1000ms ease;
transform: rotateY(0deg);
display: block;
}
.back-face-transition-enter-active {
transform: rotateY(-180deg);
display: block;
}
.back-face-transition-enter-done {
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.card-front {
display: none;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
此外,这里有一个有效的 codesandbox link 代码以防万一也有帮助。
这里有很多东西要打开。没有一个错误导致您出现问题,但有很多小错误。我会尽力解决这些问题。在大多数情况下,你的 React 是正确的,但 CSS 是你遇到麻烦的地方。
tl;dr:这是一个有效的 code sandbox
- 您需要在
active
class 上放置转换。这是约定俗成的,但对于您的特定示例,它们可能是卡片元素上的永久属性。 - transform-style保留 3d 需要在 3d 元素的父级上
- 如果您希望页面加载时正面朝前,那么您的
flipped
逻辑就是倒退的 - 你的正面有
display: none
,这意味着它根本不可见。 - 如果您希望保持变换(180 度转弯),则需要指定
exit-done
和enter-done
。将这些规则设置为与active
class 具有相同的变换值,这将使动画结束后的一侧“保持原样”。 - 背面可见性可以是面部元素的永久属性
- 背面的显示块什么也没做——它已经是块了,因为它是一个 div 元素。我想你是想把它放在 card-front 规则中。
- 需要在父元素上设置
perspective
属性 才能看到真正的 3d 效果。这是一个像素值,表示观看者与 z space. 中的元素的距离
- 需要对卡片布局进行更多调整才能使其正确。我在下面添加了我的基本样式。
- 3d 元素容器的背景(你的例子中的按钮)应该有
transparent
的背景,否则卡片在 3d 中移动时会切穿背景 space。 - 在以这种方式旋转的元素上设置一个明确的背景是个好主意,这样动画会更流畅。
我想就这些了。
代码
import { useState } from "react";
import { CSSTransition } from "react-transition-group";
import "./styles.css";
export default function App() {
const [flipped, setFlipped] = useState(false);
return (
<div className="card-container">
<button className="card-button" onClick={() => setFlipped(!flipped)}>
<CSSTransition
in={!flipped}
timeout={1000}
classNames="front-face-transition"
>
<div className="card-front">
<p>front-side</p>
</div>
</CSSTransition>
<CSSTransition
in={flipped}
timeout={1000}
classNames="back-face-transition"
>
<div className="card-back">
<p>back-side</p>
</div>
</CSSTransition>
</button>
</div>
);
}
body {
background-color: darkgray;
}
.App {
font-family: sans-serif;
text-align: center;
}
.card-container {
width: 250px;
height: 400px;
padding: 0;
margin: 0;
}
.card-container .card-button {
padding: 0;
margin: 0;
border: none;
cursor: pointer;
width: 100%;
height: 100%;
position: relative;
background: transparent;
transform-style: preserve-3d;
perspective: 5000px;
}
.card-front,
.card-back {
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 100%;
}
.card-front {
background: beige;
position: absolute;
top: 0;
left: 0;
}
.card-back {
background: aliceblue;
}
.front-face-transition-enter {
transform: rotateY(180deg);
}
.front-face-transition-enter-active {
transition: all 1000ms ease;
transform: rotateY(0deg);
}
.front-face-transition-enter-done {
transform: rotateY(0deg);
}
.front-face-transition-exit {
transform: rotateY(0deg);
}
.front-face-transition-exit-active {
transform: rotateY(180deg);
transition: all 1000ms ease;
}
.front-face-transition-exit-done {
transform: rotateY(180deg);
}
.back-face-transition-enter {
transform: rotateY(-180deg);
}
.back-face-transition-enter-active {
transform: rotateY(0deg);
transition: all 1000ms ease;
}
.back-face-transition-enter-done {
transform: rotateY(0deg);
}
.back-face-transition-exit {
transform: rotateY(0deg);
}
.back-face-transition-exit-active {
transform: rotateY(-180deg);
transition: all 1000ms ease;
}
.back-face-transition-exit-done {
transform: rotateY(-180deg);
}
总的来说,您的代码可能比较干燥。寻找相似元素的共享样式并将它们组合在一起以避免不必要的麻烦。我在代码示例中留下了一些优化方法,但是例如您可以看到 .front-face-transition-exit-done
和 .front-face-transition-enter
具有相同的规则,将它们放在一起!
祝CSS过渡顺利,如果您有任何问题,请告诉我。