简体   繁体   中英

CSS 3D animated wheel off center

I have a 3D css wheel/cylindar animation that's rotating on the x axis. My issue is the animation appears to move up and down outside of it's container. Example GIF below...

动作示例

The code for the above can be found here here: 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>

The red pane is the segments container, this is the element with the css animation. The red pane is staying within the container, however, the segments are offset vertically which is pushing them outside of the container.

I can stop this up and down movement by adding transform-origin: 50% 0; to each of the segments but this poses a new issue. Gaps between the segments! See below...

间隙示例

Code for the above: 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>

Any help would be great!

You can rectify this by adjusting the transform-origin of the rotated element like below:

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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM