如何使用CSS实现全景3D滑动轮播?- react

3
我正在努力创建一个类似于以下设计的全景3D滑动轮播图: 所需输出图像 然而,我的当前实现并没有达到相同的效果,轮播图看起来是这样的:

enter image description here

我想在CSS中实现那个轮播图。
这是我迄今为止尝试过的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 来实现这种效果,但是在用户界面上无法达到相同的效果。

我希望我的轮播图能够像这样:
enter image description here

有人可以帮我调整 CSS 以实现所需的效果吗?

3
https://stackoverflow.com/questions/75837463/how-to-get-this-curve-effect-using-css-with-reactjs/75886591#75886591 - undefined
3个回答

2
我会纠正你的初始解决方案,以便按照你的方向继续工作。
  1. 我建议将瓷砖放入一个弹性容器中,而不是使用position: absolute。将.coverflow-container设置为弹性容器。然后,你就不必为每个元素应用水平过渡效果。相反,当活动瓷砖发生变化时,你可以对整个容器进行移动。
  2. 我建议在每个瓷砖上应用transformZ,而不是使用缩放。由于你在瓷砖容器上使用了perspective,我们可以在这里利用它的优势,将瓷砖从前面向后移动。离中心越近的瓷砖,通过Z轴移动得越远。
  3. 为了获得更柔和的效果,我还会逐步对每个元素应用rotateY - 离中心越远的瓷砖,在Y轴上的旋转角度越大。此外,瓷砖旋转得越多,它就会越“缩小”,所以我们需要将其靠近中心。为此,我们使用translateX
  4. 请记住,变换的顺序很重要。所以我们先将瓷砖移动到其位置,然后再进行旋转。

这些是我所做的主要更改。

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 解决方案将如下所示: enter image description here

0

重复的内容:如何在ReactJS中使用CSS实现这种曲线效果?

代码片段完全来自上面链接中的@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>


-1
在你的代码中,请在第6行注释掉Overflow属性。
.coverflow-container {
perspective: 1000px;
width: 100%;
height: 250px;
position: relative;
/* overflow: hidden; */
}

它会起作用...

[输出屏幕] : https://istack.dev59.com/0kuvi.webp


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接