Анимировать фиксированный элемент к центру области просмотра - PullRequest
4 голосов
/ 07 мая 2019

У меня есть элемент position: fixed; в верхнем правом углу страницы.
Я хочу, чтобы при щелчке он "рос и двигался" к центру экрана.

Лучшее решение, которое я знаю, чтобы поместить что-то в мертвую точку страницы, это

position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);

Все отлично работает, если у меня элемент изначально расположен со свойствами top и left, но в анимации есть неприятный скачок, если элемент изначально позиционирован с right вместо left.

const myFunc = function() {
  let f = document.getElementById('element')

  if (f.className.includes('bar')) {
    f.className = 'foo'
  } else {
    f.className = 'foo bar'
  }
}
.wrapper {
  position: relative;
  width: 100%;
  height: 100%;
}

.foo {
  position: fixed;
  top: 20px;
  right: 20px;
  width: 200px;
  height: 50px;
  background-color: blue;
  transition: 0.5s all;
}

.bar {
  position: fixed;
  top: 50%;
  left: 50%;
  width: 500px;
  height: 500px;
  background-color: red;
  transform: translate(-50%, -50%);
  transition: 0.5s all;
}
<div class="wrapper">
  <div class="foo" id="element" onclick="myFunc()">
  </div>
</div>

Codepen

Как мне избавиться от начального прыжка в анимации к горизонтальному центру? (т. е. я хочу наоборот "сужение к верху справа", здесь все работает нормально).

Ответы [ 2 ]

3 голосов
/ 07 мая 2019

Вам просто нужно изменить справа налево в состоянии foo.
Это также подразумевает, что вы измените свойство translate на: translate(50%,-50%);, так как значение tanslateX должно быть слева направо, чтобы центрировать элемент:

const myFunc = function () {
  let f = document.getElementById('element')

  if(f.className.includes('bar')) {
    f.className = 'foo'
  }
  else {
    f.className = 'foo bar'
  }
}
.wrapper {
  position: relative;
  width: 100%;
  height: 100%;
}

.foo {
  position: fixed;
  top: 20px;
  right: 20px;
  width: 200px;
  height: 50px;
  background-color: blue;
  transition: 0.5s all;
}

.bar {
  position: fixed;
  top: 50%;
  right: 50%;
  width: 500px;
  height: 500px;
  background-color: red;
  transform: translate(50%, -50%);
  transition: 0.5s all;
}
<div class="wrapper">
  <div class="foo" id="element" onclick="myFunc()">
  </div>
</div>

На заметку, если вы знаете размер вашего элемента в обоих состояниях, вы можете выполнить переход только для свойств top и right, используя calc(), например:

const myFunc = function() {
  let f = document.getElementById('element')

  if (f.className.includes('bar')) {
    f.className = 'foo'
  } else {
    f.className = 'foo bar'
  }
}
.wrapper {
  position: relative;
  width: 100%;
  height: 100%;
}

.foo {
  position: fixed;
  top: 20px;
  right: 20px;
  width: 200px;
  height: 50px;
  background-color: blue;
  transition: 0.5s all;
}

.bar {
  position: fixed;
  top: calc(50% - 250px);
  right: calc(50% - 250px);
  width: 500px;
  height: 500px;
  background-color: red;
  transition: 0.5s all;
}
<div class="wrapper">
  <div class="foo" id="element" onclick="myFunc()">
  </div>
</div>

Это изменяет траекторию анимации и предотвращает анимирование элемента в одном направлении с верхним / правым и другим с помощью свойства transform.

0 голосов
/ 07 мая 2019

Признаюсь, это поначалу доставило мне некоторые неприятности, но с некоторой настойчивостью я смог вас туда доставить. Lol

Это потому, что вы не даете CSS-переходу отправную точку, с которой нужно связать позиционирование свойства right. Вы перешли от присвоения элементу свойства right 20px к свойству left 50%. Для желаемого эффекта вам нужно задать ему начальную right позицию 20px и конечную right позицию 50% для .bar (избавление от left: 50%; ).

Теперь, после того, как вы исправите вышеупомянутую проблему, вам нужно будет обратиться к методу .bar class transform, сделав его transform: translate(50%, -50%); Это потому, что мы перешли на использование right позиционирования по оси x так что нам нужно, чтобы он шел 50% справа, а не -50% (что привело бы к тому, что элемент вышел бы за пределы экрана -50% пространства от мертвой точки родителя).

Вот ваше новое живое демо . Надеюсь, это имеет смысл :) Логически CSS требует, чтобы все переходы имели начальную точку и действительную сожительственную конечную точку. Некоторые браузеры делают это за вас, но они никогда не должны этого делать, потому что это помешает кроссплатформенной разработке.

...