【问题标题】:react-transition-group card flip animationreact-transition-group 卡片翻转动画
【发布时间】:2021-04-23 01:20:02
【问题描述】:

我对 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 链接,以防万一也有帮助。

【问题讨论】:

  • 好吧,链接的项目对我来说根本不起作用。当我点击它时它应该翻转吗?
  • 抱歉,不知道为什么链接不起作用。是的,总体结果应该是沿 y 轴翻转卡片,露出卡片的背面。
  • 链接有效 - 代码无效。卡片不会翻转。

标签: css reactjs css-animations react-transition-group


【解决方案1】:

这里有很多东西要解压。没有一个错误会导致您出现问题,而是有很多小错误。我会尽力解决它们。在大多数情况下,你的 React 是正确的,但 CSS 是你遇到麻烦的地方。

tl;dr:这是一个有效的code sandbox

  1. 您需要在active 类上放置转换。这是按照惯例,但在您的特定示例中,它们可能是卡片元素上的永久属性。
  2. transform-style 保留 3d 需要在 3d 元素的父级上
  3. 如果您希望在页面加载时正面朝向,那么您的 flipped 逻辑是向后的
  4. 您的正面有display: none,这意味着它根本不可见。
  5. 如果您希望变换保持不变(180 度转弯),则需要指定 exit-doneenter-done。将这些规则设置为与 active 类具有相同的变换值,这将使动画在动画结束后保持“原地不动”。
  6. 背面可见性可以是面部元素的永久属性
  7. 背面的显示块什么也没做——它已经是块,因为它是一个 div 元素。我想你的意思是把它放在卡片正面规则上。
  8. 需要在父元素上设置perspective 属性才能看到真正的3d 效果。这是一个像素值,表示观察者与 z 空间中的元素的距离。
  9. 需要对卡片布局进行更多调整才能使其正确。我在下面添加了我的基本样式。
  10. 3d 元素容器的背景(在你的例子中是按钮)的背景应该是transparent,否则卡片在 3d 空间中移动时会切穿背景。
  11. 最好在以这种方式旋转的元素上设置明确的背景,这样动画会更流畅。

我认为这就是一切。

代码

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 具有相同的规则,将它们放在一起!

祝 CSSTransitions 好运,如果您有任何问题,请告诉我。

【讨论】:

    猜你喜欢
    • 2013-11-22
    • 2014-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-04
    • 2019-01-17
    • 2017-10-20
    相关资源
    最近更新 更多