CSS 3D动画轮子偏离中心

7

我有一个在x轴上旋转的3D css轮/圆柱形动画。我的问题是动画似乎在其容器之外上下移动。以下是示例GIF...

Movement example

上述代码可以在这里找到:https://jsfiddle.net/thelevicole/bkt0v1mc/

(function($) {

  const $wheel = $('.wheel .wheel__inner');
  const items = 28;
  const diameter = $wheel.height();
  const radius = diameter / 2;
  const angle = 360 / items;
  const circumference = Math.PI * diameter;
  const height = circumference / items;

  for (let i = 0; i < items; i++) {
    var transform = `rotateX(${ angle * i }deg) translateZ(${ radius }px)`;

    $('<div>', {
      class: 'wheel__segment'
    }).css({
      'transform': transform,
      'height': height,
    }).html(`<span>Item ${ i }</span>`).appendTo($wheel);
  }

})(jQuery);
*,
*:before,
*:after {
  box-sizing: border-box;
}

.wheel {
  perspective: 1000px;
  border: 1px solid #333;
  margin: 50px;
}

.wheel .wheel__inner {
  background-color: red;
  position: relative;
  width: 200px;
  height: 350px;
  margin: 0 auto;
  transform-style: preserve-3d;
  animation-iteration-count: infinite;
  animation-timing-function: linear;
  animation-name: spin;
  animation-duration: 6s;
}

.wheel .wheel__inner .wheel__segment {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 40px;
  position: absolute;
  top: 50%;
  background-color: #ccc;
}

.wheel .wheel__inner .wheel__segment:nth-child(even) {
  background-color: #ddd;
}

@-webkit-keyframes spin {
  0% {
    transform: rotateX(360deg);
  }
  50% {
    transform: rotateX(180deg);
  }
  100% {
    transform: rotateX(0deg);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wheel">
  <div class="wheel__inner">
  </div>
</div>

红色窗格是分段容器,这是具有 CSS 动画的元素。红色窗格保持在容器内部,但是,分段垂直偏移,这将它们推出容器。

我可以通过为每个分段添加 transform-origin: 50% 0; 来停止上下运动,但这会引起新问题。分段之间有间隙!如下所示...

Gap example

上面的代码:https://jsfiddle.net/thelevicole/bkt0v1mc/1/

( function( $ ) {

    const $wheel = $( '.wheel .wheel__inner' );
    const items = 28;
    const diameter = $wheel.height();
    const radius = diameter / 2;
    const angle = 360 / items;
    const circumference = Math.PI * diameter;
    const height = circumference / items;
    
    for ( let i = 0; i < items; i++ ) {
        var transform = `rotateX(${ angle * i }deg) translateZ(${ radius }px)`;

        $( '<div>', {
            class: 'wheel__segment'
        } ).css( {
            'transform': transform,
            'height': height,
        } ).html( `<span>Item ${ i }</span>` ).appendTo( $wheel );
    }
    
} )( jQuery );
*, *:before, *:after {
  box-sizing: border-box;
}

.wheel {
  perspective: 1000px;
  border: 1px solid #333;
  margin: 50px;
}
.wheel .wheel__inner {
  background-color: red;
  position: relative;
  width: 200px;
  height: 350px;
  margin: 0 auto;
  transform-style: preserve-3d;
  animation-iteration-count: infinite;
  animation-timing-function: linear;
  animation-name: spin;
  animation-duration: 6s;
}
.wheel .wheel__inner .wheel__segment {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 40px;
  position: absolute;
  top: 50%;
  background-color: #ccc;
  transform-origin: 50% 0;
}
.wheel .wheel__inner .wheel__segment:nth-child(even) {
  background-color: #ddd;
}

@-webkit-keyframes spin {
  0% {
    transform: rotateX(360deg);
  }
  50% {
    transform: rotateX(180deg);
  }
  100% {
    transform: rotateX(0deg);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wheel">
    <div class="wheel__inner">
    </div>
</div>

任何帮助都将是极好的!
1个回答

7
您可以通过调整旋转元素的transform-origin来纠正这一问题,如下所示:
transform-origin: 50% calc(50% + height/2);

( function( $ ) {

    const $wheel = $( '.wheel .wheel__inner' );
    const items = 28;
    const diameter = $wheel.height();
    const radius = diameter / 2;
    const angle = 360 / items;
    const circumference = Math.PI * diameter;
    const height = circumference / items;
    
    for ( let i = 0; i < items; i++ ) {
        var transform = `rotateX(${ angle * i }deg) translateZ(${ radius }px)`;

        $( '<div>', {
            class: 'wheel__segment'
        } ).css( {
            'transform': transform,
            'height': height,
        } ).html( `<span>Item ${ i }</span>` ).appendTo( $wheel );
    }
  $wheel.css('transform-origin','50% calc(50% + '+height/2+'px)');
  $wheel.css('margin-top','-'+height+'px'); /* negative margin here to keep the element into the center */
    
} )( jQuery );
*, *:before, *:after {
  box-sizing: border-box;
}

.wheel {
  perspective: 1000px;
  border: 1px solid #333;
  margin: 50px;
}
.wheel .wheel__inner {
  background-color: red;
  position: relative;
  width: 200px;
  height: 350px;
  margin: 0 auto ; 
  transform-style: preserve-3d;
  animation-iteration-count: infinite;
  animation-timing-function: linear;
  animation-name: spin;
  animation-duration: 6s;
}
.wheel .wheel__inner .wheel__segment {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 40px;
  position: absolute;
  top: 50%;
  background-color: #ccc;
}
.wheel .wheel__inner .wheel__segment:nth-child(even) {
  background-color: #ddd;
}

@-webkit-keyframes spin {
  0% {
    transform: rotateX(360deg);
  }
  50% {
    transform: rotateX(180deg);
  }
  100% {
    transform: rotateX(0deg);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wheel">
    <div class="wheel__inner">
    </div>
</div>


非常快速的响应和可行的解决方案。谢谢!https://jsfiddle.net/thelevicole/bkt0v1mc/2/ - Levi Cole

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