3

我一直在尝试使用 React 和 vanilla css 创建类似动画的里程表。到目前为止,它的工作原理是当数字增加时,translationY会像实际的里程表一样向上发生。我目前的问题是,当它从 9 变为 0 时,它translationY发生在相反的方向(向下而不是向上)。我希望它仍然朝着相同的方向(向上)前进,但非常坚持如何做到这一点。任何帮助将不胜感激...

代码在这里:https ://codesandbox.io/s/inspiring-ellis-jpzx2

4

1 回答 1

1

我花了太多时间寻找解决方案。首先,有很多库可以让这样的事情变得微不足道,但是我很享受寻找解决方案的学习过程。

我没有创建特定于 react 的解决方案,但我的 vanilla javascript 演示应该足以轻松地将其移植到 react 解决方案中。

为了完成这个任务,我首先尝试在每次发生变化时创建一个元素,底部的数字是起始编号,顶部的数字是着陆编号,然后向下滑动直到达到所需的数字,然后制作旧元素消失。然而,当元素快速更改时,这最终看起来不连贯,并产生了一些意想不到的效果。

在偶然发现一些演示后,我意识到 3d css 可能是完美的解决方案。我们可以创建一个在轮子上旋转的 3d 元素,而不是让我们上下转换的 2d 元素。Js 可以计算旋转元素始终向前旋转所需的度数。

请欣赏我的小演示,如果您有任何问题,请提出。

const $ = (str, dom = document) => [...dom.querySelectorAll(str)];

const panels = $(".panel");
panels.forEach((panel, i) => {
  panel.style.setProperty("--angle", `${360 / panels.length * i}deg`)
});
const ring = $(".ring")[0];
const nums = $(".num");
nums.forEach((num, i) => {
  num.addEventListener("click", () => {
    const numAngle = 36 * i;
    const currentAngle =
      ring.style.getPropertyValue("--deg")
      .replace(/\D/g, "");
    let nextAngle = numAngle;
    while (nextAngle < currentAngle) {
      nextAngle += 360;
    }
    ring.style.setProperty("--deg", `-${nextAngle}deg`)
  });
});
* {
 margin: 0;
 padding: 0;
 box-sizing: border-box;
 font-family: monospace;
}

body {
 display: grid;
 place-items: center;
 min-height: 100vh;
 perspective: 500px;
 perspective-origin: 50% 50%;
}

.ring {
  transform-style: preserve-3d;
  transition: transform 1s;
  transform: rotateX(var(--deg));
}

.panel {
  position: absolute;
  transform:
    translate(-50%, -50%)
    rotateX(var(--angle))
    translateZ(22.5px);
  border-bottom: 1px solid black;
  background-color: white;
}

.numPanel {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  display: flex;
  justify-content: center;
  gap: 1rem;
  user-select: none;
}

.num {
  font-size: 2rem;
  padding: 0.5rem;
  cursor: pointer;
}

.num:hover {
  background-color: lightblue;
}
<div class="numPanel">
  <div class="num">0</div>
  <div class="num">1</div>
  <div class="num">2</div>
  <div class="num">3</div>
  <div class="num">4</div>
  <div class="num">5</div>
  <div class="num">6</div>
  <div class="num">7</div>
  <div class="num">8</div>
  <div class="num">9</div>
</div>
<div class="ring">
  <div class="panel">0</div>
  <div class="panel">1</div>
  <div class="panel">2</div>
  <div class="panel">3</div>
  <div class="panel">4</div>
  <div class="panel">5</div>
  <div class="panel">6</div>
  <div class="panel">7</div>
  <div class="panel">8</div>
  <div class="panel">9</div>
</div>

于 2021-12-19T06:51:16.507 回答