При использовании transform rotate остановить смещение содержимого

Я использую transform: rotate(); чтобы повернуть содержимое в & Вне поля зрения, однако, каждый текст находится в другом положении, когда он появляется в поле зрения. Поэтому, когда вы нажимаете кнопку "Далее" в моей демонстрации, если вы посмотрите на границу, содержимое находится в разных позициях.

при нажатии следующей кнопки колесо вращается одинаково на 90 градусов, поэтому я ожидаю, что содержимое будет в том же положении при каждом вращении. Может кто-нибудь объяснить/решить, почему этого не происходит?

Я создал колесо для моего контента, и я стилизовал колесо, чтобы скрыть параметры, которые в настоящее время не видны;

// Page load transform start, setters
var degree = 0;
var itemStart = $('.wheel').find('.item-one').addClass('item-active');
var itemNext = $('.wheel').find('.item-four').addClass('item-prev');

// On click
$('.next').click(function() {
  var wheel = $('.wheel');

  // Increment rotation
  degree += 90;
  wheel.css({
    WebkitTransform: 'rotate(' + degree + 'deg)'
  });

  // Update setter
  itemStart = $('.wheel').find('.item-active');
  itemNext = $('.wheel').find('.item-prev');

  // Add Animation
  $(itemStart).addClass('fadeOut');
  $(itemNext).addClass('fadeIn');

  //If were at the end
  var getStartPrev = $(itemStart).prev();
  var getNextPrev = $(itemNext).prev();

  if (getStartPrev.length == 0) {
    $(itemStart).removeClass('item-active');
    $(itemNext).prev().addClass('item-prev');
    $('.item-four').addClass('item-active').removeClass('item-prev');
  } else {
    $(itemStart).removeClass('item-active');
    $(itemNext).removeClass('item-prev').addClass('item-active');
    $(itemNext).prev().addClass('item-prev');
  }

  if (getNextPrev.length == 0) {
    $('.item-four').addClass('item-prev');
  }

  // Remove Animation
  setTimeout(function() {
    $('.wheel').find('.item').removeClass('fadeIn fadeOut');
  }, 400);
});
.wheel-wrp {
  position: relative;
  height: 700px;
  width: 700px;
}

.wheel {
  height: 700px;
  width: 700px;
  transition: 0.75s;
  border-radius: 50%;
  position: relative;
  background: #fff;
  left: -350px;
}

.item {
  width: 250px;
  position: absolute;
  opacity: 0;
}

.item-active {
  opacity: 1;
}

.item-one {
  bottom: 300px;
  left: 450px;
}

.item-two {
  bottom: 20px;
  left: 230px;
  -webkit-transform: rotate(90deg);
  -moz-transform: rotate(90deg);
  transform: rotate(90deg);
}

.item-three {
  bottom: 320px;
  left: 0px;
  -webkit-transform: rotate(180deg);
  -moz-transform: rotate(180deg);
  transform: rotate(180deg);
}

.item-four {
  top: 20px;
  left: 230px;
  -webkit-transform: rotate(270deg);
  -moz-transform: rotate(270deg);
  transform: rotate(270deg);
}

.current-item {
  bottom: 300px;
  left: 450px;
}

.next-item {
  top: 20px;
  left: 230px;
  -webkit-transform: rotate(0deg);
  -moz-transform: rotate(0deg);
  transform: rotate(-90deg);
  opacity: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="page">
  <div class="wheel-wrp">
    <div class="wheel">
      <div class="item item-one">
        <h4>Project 1 - beautifully crafted digital brand</h4>
        <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
      </div>
      <div class="item item-two">
        <h4>Project 2 - redefining technological boundaries</h4>
        <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
      </div>
      <div class="item item-three">
        <h4>Project 3 - Beauty in Design</h4>
        <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
      </div>
      <div class="item item-four">
        <h4>Project 4 - simply stunning </h4>
        <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
      </div>
    </div>
  </div>
</div>
<div class="next">Next</div>

пример демо - https://codepen.io/SamXronn/pen/opqWbq

4 ответов


вот мой пойти на это.

  • я установил начало преобразования элементов в левом верхнем углу (та же точка, что и для позиционирования)

  • использование transform translateY и translateX, каждый деталь можно после этого поместить против колеса, независимо от их ширины и высоты

  • вам не нужен jQuery для анимации. Просто используйте его для переключения активного класса. Тот же результат достигается гораздо более плавно и с гораздо меньшим количеством кода с CSS3 анимация и "активный" класс.

Codepen здесь

let currentItem = 0
const $wheel = $('.wheel'),
      $items = $wheel.find(".item")

$('.next').click(() => rotate(1));
$('.prev').click(() => rotate(-1));

const rotate = direction => {
    currentItem -= direction
    $wheel.css("transform",`rotate(${-currentItem*90}deg)`)
    $items.removeClass("active")
          .eq(currentItem%$items.length)
          .addClass("active")

}
body {
  background-color: #2c3e50;
}
button {
  background: #2980b9;
  padding: 15px 35px;
  color: #fff;
  float: left;
  position: relative;
  z-index: 9999;
  cursor: pointer;
}
.wheel {
  height: 700px;
  width: 700px;
  transition: transform 0.75s;
  border-radius: 50%;
  position: relative;
  background: #fff;
}
.item {
  width: 250px;
  position: absolute;
  opacity: 0.2;
  transition: opacity 0.75s;
  border: 1px solid #f00;
  transform-origin: top left;
}
.item:nth-child(1) {
  top: 50%;
  left: 100%;
  transform: translateY(-50%) translateX(-100%);
}
.item:nth-child(2) {
  top: 100%;
  left: 50%;
  transform: rotate(90deg) translateY(-50%) translateX(-100%);
}
.item:nth-child(3) {
  left: 0;
  top: 50%;
  transform: rotate(180deg) translateY(-50%) translateX(-100%);
}
.item:nth-child(4) {
  top: 0;
  left: 50%;
  transform: rotate(270deg) translateY(-50%) translateX(-100%);
}
.item.active {
  opacity: 1;
}
h4 {
  margin: 0px 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>

<div id="page">
    <div class="wheel">
      <div class="item active">
        <h4>Project 1 - beautifully crafted digital brand</h4>
        <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
      </div>
      <div class="item">
        <h4>Project 2 - redefining technological boundaries</h4>
        <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
      </div> 
      <div class="item">
        <h4>Project 3 - Beauty in Design</h4>
        <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
      </div> 
      <div class="item">
        <h4>Project 4 - simply stunning </h4>
        <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
      </div>
    </div>
</div>
<button class="prev">Prev</button>
<button class="next">Next</button>

довольно сложным. Проблема заключается в сочетании вертикального центрирования для ваших divs имеют разные высоты, и ваше абсолютное позиционирование с px. И трансформация вращается, конечно

Я вышел с решением, используя типичный top:50; transform:-50% вертикальный центрирующий Хак, адаптированный к различным вращениям div.

это позаботится о вертикальном выравнивании полностью предсказуемыми и вычисляемыми значениями. Горизонтальное выравнивание с другой стороны доказывает будьте хитрее, может быть, я что-то упускаю здесь, но я придумал решение для них с помощью магических чисел ( % , которые работают, хотя я не уверен почему)... Во всяком случае, вот фрагмент

// Page load transform start, setters
var degree = 0;
var itemStart = $('.wheel').find('.item-one').addClass('item-active');
var itemNext = $('.wheel').find('.item-four').addClass('item-prev');

// On click
$('.next').click( function() {
  var wheel = $('.wheel');
  
  // Increment rotation
  degree += 90;
  wheel.css({ WebkitTransform: 'rotate(' + degree + 'deg)'});
    
  // Update setter
  itemStart = $('.wheel').find('.item-active');
  itemNext = $('.wheel').find('.item-prev');

  // Add Animation
  $(itemStart).addClass('fadeOut');
  $(itemNext).addClass('fadeIn');
  
  //If were at the end
  var getStartPrev = $(itemStart).prev();
  var getNextPrev = $(itemNext).prev();
  
  if( getStartPrev.length == 0 ) {
    $(itemStart).removeClass('item-active');
    $(itemNext).prev().addClass('item-prev');
    $('.item-four').addClass('item-active').removeClass('item-prev');
  } else {
    $(itemStart).removeClass('item-active');
    $(itemNext).removeClass('item-prev').addClass('item-active');
    $(itemNext).prev().addClass('item-prev');   
  }
  
  if( getNextPrev.length == 0 ) {
    $('.item-four').addClass('item-prev');
  }
  
   // Remove Animation
   setTimeout(function(){ 
    $('.wheel').find('.item').removeClass('fadeIn fadeOut');
   }, 400);
});
body{
 background-color:  #2c3e50; 
}

.next{
  background: #2980b9;
  padding: 15px 35px;
  color: #fff;
  float: left;
  position: relative;
  z-index: 9999;
  cursor: pointer;
}

.wheel-wrp{
  position: relative;
  height: 700px;
  width: 700px;
}

.wheel{
  height: 700px;
  width: 700px;
  transition: 0.75s;
  border-radius: 50%;
  position: relative;
  background: #fff;
  left: -350px;
}
.item{
  width: 250px;
  position: absolute;
  opacity: 0;
  border: 1px solid red;
}
.item-active{
  opacity: 1;
}
.item-one {
    top: 50%;
    transform: translateY(-50%);
    left: 75%;
}

.item-two {
    right: 50%;
    top: 83%;
    transform: translateX(50%) rotate(90deg);
}

.item-three {
    top: 50%;
    right: 75%;
    transform: rotate(180deg) translateY(50%);
}

.item-four {
    left: 50%;
    bottom: 84%;
    transform: translateX(-50%) rotate(270deg);
}

.current-item{
  bottom: 300px;
  left: 450px;
}

.next-item{
  top: 20px;
  left: 230px;
  -webkit-transform:rotate(0deg);
  -moz-transform:rotate(0deg);
  transform:rotate(-90deg);
  opacity: 0;
}

h4{
  margin:0px 0px;
}


.fadeOut{
  animation: menuFadeOut 350ms;
  webkit-animation-fill-mode: forwards;
  animation-fill-mode: forwards;  
}

.fadeIn{
  animation: menuFadeIn 1500ms;
  webkit-animation-fill-mode: forwards;
  animation-fill-mode: forwards;
}

@keyframes menuFadeOut {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

@keyframes menuFadeIn {
  0% {
    opacity: 0;
  } 
  100% {
    opacity: 1;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>

<div id="page">
  <div class="wheel-wrp">
    <div class="wheel">
      <div class="item item-one">
        <h4>Project 1 - beautifully crafted digital brand</h4>
        <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
      </div>
      <div class="item item-two">
        <h4>Project 2 - redefining technological boundaries</h4>
        <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
      </div> 
      <div class="item item-three">
        <h4>Project 3 - Beauty in Design</h4>
        <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
      </div> 
      <div class="item item-four">
        <h4>Project 4 - simply stunning </h4>
        <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum..</p>
      </div>
    </div>
  </div>
</div>
<div class="next">Next</div>

единственные изменения в определении конкретных элементов, так что если вы хотите, чтобы проверить на перо для лучшей видимости, это часть, которую вы должны заменить:

.item-one {
    top: 50%;
    transform: translateY(-50%);
    left: 75%;
}

.item-two {
    right: 50%;
    top: 83%;
    transform: translateX(50%) rotate(90deg);
}

.item-three {
    top: 50%;
    right: 75%;
    transform: rotate(180deg) translateY(50%);
}

.item-four {
    left: 50%;
    bottom: 84%;
    transform: translateX(-50%) rotate(270deg);
}

надеюсь, что это поможет. И если каким-либо образом кому-то хочется объяснить + фиксация эти магические числа, которые были бы очень рады ;)


и это моя проба :) я удалил item-one two.. классы и используемые css nth-child селекторы и подготовили Первоначальный макет колеса сначала с помощью CSS, используя transform-origin к центру круга, а затем повернул само колесо. Возвращение в исходное положение было сложным, потому что оно анимировало обратное направление şn при вращении от 270deg до 0deg. Поэтому я добавил дополнительный класс, чтобы мгновенно перейти в исходное положение без анимации.

$(".next").on("click", function () {
        var wheel = $(".wheel");
        if (wheel.hasClass("rotate-1")) {
            wheel.removeClass("rotate-1").addClass("rotate-2");
        }
        else if (wheel.hasClass("rotate-2")) {
            wheel.removeClass("rotate-2").addClass("rotate-3");
        }
        else if (wheel.hasClass("rotate-3")) {
            wheel.removeClass("rotate-3").addClass("rotate-4");
        }
        else if (wheel.hasClass("rotate-4")) {
            wheel.removeClass("rotate-4").addClass("rotate-5").delay(1000).queue(function (next) {
                $(this).addClass("rotate-1");
                $(this).removeClass("rotate-5");
                next();
            });
        }

    });
.wheel {
            border-radius: 50%;
            background: rebeccapurple;
            width: 700px;
            height: 700px;
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
            transition: all 1s ease;
            margin-left : -350px;
        }

        .item {
            background:transparent;
            color: white;
            width: 250px;
            margin-right: 10px;
            margin-left: calc(50% - 135px);
            position: absolute;
            transform-origin: calc(-50% + 35px) 50%;
            transition: all 1s ease;
        }

        .wheel.rotate-1 {
            transform: rotateZ(0deg);
            transition: all 0s ease;
        }

        .wheel.rotate-2 {
            transform: rotateZ(90deg);
        }

        .wheel.rotate-3 {
            transform: rotateZ(180deg);
        }

        .wheel.rotate-4 {
            transform: rotateZ(270deg);
        }

        .wheel.rotate-5 {
            transform: rotateZ(360deg);
        }

        .item:nth-child(1) {
            transform: rotateZ(0deg);
        }

        .item:nth-child(2) {
            transform: rotateZ(-90deg);
        }

        .item:nth-child(3) {
            transform: rotateZ(-180deg);
        }

        .item:nth-child(4) {
            transform: rotateZ(-270deg);
        }

        .wheel.rotate-1 .item {
            opacity: 0;
        }
        .wheel.rotate-1 .item:nth-child(1) {
            opacity: 1;
        }
        .wheel.rotate-2 .item {
            opacity: 0;
        }
        .wheel.rotate-2 .item:nth-child(2) {
            opacity: 1;
        }
        .wheel.rotate-3 .item {
            opacity: 0;
        }
        .wheel.rotate-3 .item:nth-child(3) {
            opacity: 1;
        }
        .wheel.rotate-4 .item {
            opacity: 0;
        }
        .wheel.rotate-4 .item:nth-child(4) {
            opacity: 1;
        }
        .wheel.rotate-5 .item {
            opacity: 0;
        }
        .wheel.rotate-5 .item:nth-child(1) {
            opacity: 1;
        }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="page">
        <div class="wheel-wrp">
            <div class="wheel rotate-1">
                <div class="item">
                    <h4>Project 1 - beautifully crafted digital brand</h4>
                    <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
                        laborum..
                    </p>
                </div>
                <div class="item">
                    <h4>Project 2 - redefining technological boundaries</h4>
                    <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
                        laborum..
                    </p>
                </div>
                <div class="item">
                    <h4>Project 3 - Beauty in Design</h4>
                    <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
                        laborum..
                    </p>
                </div>
                <div class="item">
                    <h4>Project 4 - simply stunning </h4>
                    <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
                        laborum..
                    </p>
                </div>
            </div>
        </div>
    </div>
    <div class="next">Next</div>

возможно, это не совсем правильное решение, но оно работает правильно.

Я изменил отображение собственность .item поигрывать. И сделал некоторые манипуляции с transform-origin и положение элементов

body{
 background-color:  #2c3e50; 
}

.next{
  background: #2980b9;
  padding: 15px 35px;
  color: #fff;
  float: left;
  position: relative;
  z-index: 9999;
  cursor: pointer;
}

.wheel-wrp{
  position: relative;
  height: 700px;
  width: 700px;
}

.wheel{
  height: 700px;
  width: 700px;
  transition: 0.75s;
  border-radius: 50%;
  position: relative;
  background: #fff;
  left: -350px;
  transform-origin: center;
}
.item{
	width: 250px;
    height: 100%;
    flex-direction: column;
    display: flex;
    justify-content: center;
    position: absolute;
    opacity: 0;
    border: 1px solid red;
    transform-origin: center;
}
.item-active{
  opacity: 1;
}
.item-one{
  right: 0;
}

.item-two{
  -webkit-transform: rotate(90deg);
    -moz-transform: rotate(90deg);
    transform: rotate(90deg);
    bottom: 250px;
    transform-origin: bottom left;
}

.item-three{
  left: 0px;
    -webkit-transform: rotate(180deg);
    -moz-transform: rotate(180deg);
    transform: rotate(180deg);
}

.item-four{
      bottom: -250px;
    transform-origin: top left;
    -webkit-transform: rotate(270deg);
    -moz-transform: rotate(270deg);
    transform: rotate(270deg); 
}

.current-item{
  bottom: 300px;
  left: 450px;
}

.next-item{
  top: 20px;
  left: 230px;
  -webkit-transform:rotate(0deg);
  -moz-transform:rotate(0deg);
  transform:rotate(-90deg);
  opacity: 0;
}

h4{
  margin:0px 0px;
}


.fadeOut{
  animation: menuFadeOut 350ms;
  webkit-animation-fill-mode: forwards;
  animation-fill-mode: forwards;  
}

.fadeIn{
  animation: menuFadeIn 1500ms;
  webkit-animation-fill-mode: forwards;
  animation-fill-mode: forwards;
}

@keyframes menuFadeOut {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

@keyframes menuFadeIn {
  0% {
    opacity: 0;
  } 
  100% {
    opacity: 1;
  }
}