javascript 如何用CSS实现全景3D旋转木马?- react

rt4zxlrg  于 2023-11-15  发布在  Java
关注(0)|答案(3)|浏览(113)

bounty已结束。回答此问题有资格获得+100声望赏金。赏金宽限期将在1小时后结束。Smack Alpha正在寻找来自信誉良好的来源的答案

我正在创建一个类似于以下设计的全景3D旋转木马:

然而,我目前的实现没有达到同样的效果,旋转木马看起来像这样:



我想在CSS中实现这个carousel
以下是我目前为止尝试过的CSS代码:

.coverflow-container {
  perspective: 1000px;
  width: 100%;
  height: 250px;
  position: relative;
  overflow: hidden;
}

.coverflow-item {
  position: absolute;
  width: 200px; /* Width of each slide */
  height: 250px; /* Height of non-active slides */
  left: 50%;
  transform-origin: center;
  transition: transform 0.5s ease, z-index 0s linear, height 0.5s ease;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #b5b4b6;
  color: white;
  border: 1px solid black;
  box-sizing: border-box;
  opacity: 0.7;
}

.coverflow-item.active {
  background: #272a36;
  z-index: 3;
  opacity: 1;
  height: 90%; /* Larger height for the active slide */
}

.coverflow-controls {
  position: absolute;
  width: 100%;
  bottom: 10px;
  text-align: center;
  padding-top: 100px;
}

button {
  padding: 10px;
  margin: 0 10px;
  font-size: 16px;
  cursor: pointer;
}

字符串
这是我的CodeSandbox的链接:https://codesandbox.io/s/coverflow-swiper-5kywvv?file=/src/App.css
我试着调整CSS来达到这个效果。但是我无法在UI中得到同样的效果。
我希望我的旋转木马是这样的

有没有人可以帮助我如何调整我的CSS,以达到预期的效果?

g0czyy6m

g0czyy6m1#

我会纠正你最初的解决方案,继续朝你的方向努力。
1.我会把tiles放到一个flex容器中,而不是使用position: absolute。把.coverflow-container作为一个flex。这样,你就不必对每个元素应用horismatic transition。相反,当活动tile改变时,你可以对整个容器进行移位。
1.我建议不要使用scale,而是在每个tile上应用transformZ。因为你在tiles容器上使用perspective,我们可以在tile上使用它的优势,将它们从前面移回来。tile离中心越近,Z轴就越远。
1.为了获得更柔和的效果,我还将在每个元素上逐步执行rotateY-瓷砖离中心越远,Y轴上的旋转越大。此外,瓷砖旋转得越多,它就越“收缩”,因此我们需要将其移近中心。为此,我们使用translateX
1.请记住,变换的顺序很重要。所以我们首先在其位置上移动一个瓷砖,然后旋转。
以下是我做的主要改动。

const TILE_SIZE = 150;

/* the closer we to the center, the more far we move the tile */
function calcTranslateZ(index, activeIndex) {
    if (index === activeIndex) return -TILE_SIZE * 2.5;
    return -(TILE_SIZE*10 / (Math.abs(index - activeIndex) * slides.length));
}

/* the more you far from center, the smaller the gap */
function calcTranslateX(index, activeIndex) {
  if (index === activeIndex) return 0;
  return Math.pow(activeIndex - index, 3) * 10;
}

/* the closer to the center, the more "exposed the tile" */
function calcRotateY(index, activeIndex) {
  return (activeIndex - index) * 30;
}

/* we shif the container  with the tiles, so the active tile is centralized */
function calcShift(activeIndex) {
  return ((slides.length - 1) / 2 - activeIndex) * TILE_SIZE;
}

/* if a tile far from center, it looks ugly */
function shouldHideTile(index, activeIndex) {
  return Math.abs(activeIndex - index) > 2;
}
  
....
  
// and on the template side
return (
    <>
      <div
        className="coverflow-container"
        style={{
          transform: `translateX(${calcShift(activeIndex)}px)`
        }}
      >
        {slides.map((slide, index) => {
          return (
            <div
              key={slide}
              className={`
                coverflow-item ${
                   index === activeIndex ? "active" : ""
                }
                ${shouldHideTile(index, activeIndex) ? "hidden" : ""}
              `}
              style={{
                transform: `
                  translateZ(${calcTranslateZ(index, activeIndex)}px)
                  translateX(${calcTranslateX(index, activeIndex)}px)
                  rotateY(${calcRotateY(index, activeIndex)}deg) `
              }}
              onClick={() => slideTo(index)}
            >
              {slide}
            </div>
          );
        })}
      </div>
      
   ....
   </>

字符串
完整的解决方案是here
解决方案如下所示:x1c 0d1x

fcipmucu

fcipmucu2#

复制:如何使用css和reactjs获得这个曲线效果?
截图完全来自上面链接中的@imhvost代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>Swiper demo</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1" />
  <!-- Link Swiper's CSS -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@8/swiper-bundle.min.css" />

  <!-- Demo styles -->
  <style>
    html,
    body {
      position: relative;
      height: 100%;
    }

    body {
      background: #eee;
      font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
      font-size: 14px;
      color: #000;
      margin: 0;
      padding: 0;
    }

    .swiper {
      width: 100%;
      padding-top: 50px;
      padding-bottom: 50px;
    }

    .swiper-slide {
      background-position: center;
      background-size: cover;
      width: 100px;
      height: 100px;
    }

    .swiper-slide img {
      display: block;
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
  </style>
</head>

<body>
  <!-- Swiper -->
  <div class="swiper mySwiper">
    <div class="swiper-wrapper">
      <div class="swiper-slide">
        <img src="https://swiperjs.com/demos/images/nature-1.jpg" />
      </div>
      <div class="swiper-slide">
        <img src="https://swiperjs.com/demos/images/nature-2.jpg" />
      </div>
      <div class="swiper-slide">
        <img src="https://swiperjs.com/demos/images/nature-3.jpg" />
      </div>
      <div class="swiper-slide">
        <img src="https://swiperjs.com/demos/images/nature-4.jpg" />
      </div>
      <div class="swiper-slide">
        <img src="https://swiperjs.com/demos/images/nature-5.jpg" />
      </div>
      <div class="swiper-slide">
        <img src="https://swiperjs.com/demos/images/nature-6.jpg" />
      </div>
      <div class="swiper-slide">
        <img src="https://swiperjs.com/demos/images/nature-7.jpg" />
      </div>
      <div class="swiper-slide">
        <img src="https://swiperjs.com/demos/images/nature-8.jpg" />
      </div>
      <div class="swiper-slide">
        <img src="https://swiperjs.com/demos/images/nature-9.jpg" />
      </div>
    </div>
    <div class="swiper-pagination"></div>
  </div>

  <!-- Swiper JS -->
  <script src="https://cdn.jsdelivr.net/npm/swiper@8/swiper-bundle.min.js"></script>

  <!-- Initialize Swiper -->
  <script>
    var swiper = new Swiper(".mySwiper", {
      effect: "coverflow",
      grabCursor: true,
      centeredSlides: true,
      slidesPerView: "auto",
      spaceBetween: 10,
      loop: true,
      loopedSlides: 8,
      coverflowEffect: {
        rotate: 80,
        depth: -100,
        modifier: .2,
        scale: 1.2,
      },
      pagination: {
        el: ".swiper-pagination",
        clickable: true,
      },
    });
  </script>
</body>

</html>

字符串

8yoxcaq7

8yoxcaq73#

在您的代码https://codesandbox.io/s/coverflow-swiper-5kywvv?file=/src/App.css
请在第6行中注解Overflow属性

.coverflow-container {
perspective: 1000px;
width: 100%;
height: 250px;
position: relative;
/* overflow: hidden; */
}

字符串
会成功的
[输出画面]:https://i.stack.imgur.com/0kuvi.png

相关问题