javascript - 将 div 翻译成像里程表一样的行为

标签 javascript css reactjs odometer

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

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

最佳答案

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

我没有创建特定于 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>

关于javascript - 将 div 翻译成像里程表一样的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68492082/

相关文章:

html - 我可以让一个 anchor 标签覆盖另一个 anchor 标签吗?

javascript - 如何使用根 reducer 配置存储

javascript - 我如何在 Node js中运行多个应用程序?

javascript - 脚本在子页面上不起作用

javascript - 下划线模板 - 更改标记标记

javascript - React.js 在从 Express.js 和 Restful api 获取响应之前等待 4 分钟

javascript - React : [useRef,scrollIntoView,]如何仅自动滚动溢出页面内的特定div?

javascript - 意外请求 : GET

css - 同一元素上的两个动画不起作用

html - 背景图像中的灰色 block