Анимировать фиксированный элемент в центре области просмотра

У меня есть элемент 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>

Кодепен

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

при использовании right вы можете использовать top: 50%; right: 50%; transform: translate(50%, -50%);?

kukkuz 07.05.2019 18:25

см. codepen.io/anon/pen/LoVzrR

kukkuz 07.05.2019 18:32

Сукин сын, клянусь, я пробовал все варианты этого ;-) Спасибо!

TommyF 07.05.2019 18:33
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
CSS: FlexBox
CSS: FlexBox
Ранее разработчики использовали макеты с помощью Position и Float. После появления flexbox сценарий полностью изменился.
5
3
727
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вам просто нужно изменить справа налево в состоянии 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>

Кстати, если вы знаете размер вашего элемента в обоих состояниях, вы можете сделать переход только в верхнем и правом свойствах, используя 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.

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

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

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

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

@TommyF, ты проверяешь мой ответ?

Pie 08.05.2019 09:08

Другие вопросы по теме