Можно ли использовать animate. css с уже переведенными элементами? - PullRequest
1 голос
/ 20 апреля 2020

Я использую анимацию Даниэля Идена. css на сайте. Это прекрасно работает, но у меня проблемы с элементами, к которым уже применен transform:translate().

Проблема, с которой я столкнулся:

У меня есть div, который зафиксирован в нижней части страницы, преобразован на -50% в направлении x и чуть более -100% в направлении y, чтобы отцентрировать его:

#resend_activation_div {
  position:fixed;
  top:100%;
  left:50%;
  transform:translate(-50%, calc(-100% - 10px));
}

, который выглядит как это: enter image description here

Я добавляю animated fadeOutDown к classList из div при нажатии X. Я хочу, чтобы элемент постепенно исчезал из своей позиции на странице. Проблема в том, что анимация работает следующим образом ...

@-webkit-keyframes fadeOutDown {
  from {
    opacity: 1;
  }

  to {
    opacity: 0;
    -webkit-transform: translate3d(0, 100%, 0);
    transform: translate3d(0, 100%, 0);
  }
}

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

Мой обходной путь:

Единственный способ, который я нашел, чтобы преодолеть это, - это определить новый класс с нужным мне переводом и использовать его в classList вместо ...

@-webkit-keyframes fadeOutDownWithCentering {
 from {
  opacity:1
 }
 to {
  opacity:0;
  -webkit-transform:translate3d(-50%, 100%, 0);
  transform:translate3d(-50%, 100%, 0)
 }
}

... который работает, но это означает написание нового правила для каждой анимации для каждого различного преобразования, которое я имею в своих элементах!

Итак, мой вопрос: Есть ли более разумный способ сделать это? Можно ли заставить css уважать мое исходное преобразование при выполнении преобразования в правиле анимации?

Ответы [ 2 ]

2 голосов
/ 23 апреля 2020

Объяснение

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

Чтобы достичь того, что вы хотите, используя чистый CSS, мы можем использовать calc функция для выполнения расчетов. Наряду с calc мы также будем использовать CSS пользовательских свойств , чтобы объявить начальное значение преобразования явно . Затем также сообщите CSS значение translateY (например, 30px), необходимое для анимации затухания. Поскольку calc можно использовать для работы с пользовательскими свойствами CSS, теперь мы можем вычислить желаемое конечное значение translate (например, translate: 0px calc(var(--initial-transformY) + var(--added-transformY))). Поместив все эти операции в класс (например, .fadeOutDown), теперь мы можем просто добавить этот класс к любым элементам, которые вы хотите исчезнуть.


Solution # 1

Вот пример, показывающий, как использовать пользовательские свойства CSS и calc вместе для достижения желаемого. В этом примере вы можете просто добавить класс fadeOutDown (без использования атрибута animation) к элементам, которые хотите исчезнуть. Класс добавит значение translateY к фиксированному значению 30px (вы также можете использовать пользовательское свойство CSS, если хотите).

const foo = document.querySelector('.foo')
const bar = document.querySelector('.bar')

bar.addEventListener('click', e => {
  foo.classList.toggle('fadeOutDown')
})
* {
  box-sizing: border-box;
  font-family: Helvetica;
}

html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
  overflow: hidden;
}

.foo {
  --initial-transformY: -10px;
  position: absolute;
  bottom: 0;
  left: 50%;
  width: 40%;
  background: #121212;
  color: white;
  border-radius: 5px;
  padding: 16px;
  text-align: center;
  transform: translate(-50%, var(--initial-transformY));
  /* or for Firefox, you can also use this -> translate: -50% var(--initial-transformY);*/
  transition:
    transform .5s ease,
    opacity .5s ease;
}

.fadeOutDown {
  opacity: 0;
  transform: translate(-50%, calc(var(--initial-transformY) + 30px));
  /* or for Firefox, you can also use this -> translate: -50% calc(var(--initial-transformY) + 30px) */
  /* Or you can use a CSS custom property like this (Firefox)
  --fadeOutDown-value: 30px;
  translate: -50% calc(var(--initial-transformY) + var(--fadeOutDown-value)); */
}

.bar {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 16px;
  background: #ad17fd;
  color: white;
  border: none;
  cursor: pointer;
  border-radius: 5px;
  transition: all .2s ease;
  text-transform: uppercase;
}
<div class="foo">Hello there, I am foo</div>
<button class="bar">Click me to move foo</button>

Вот пример использования свойства animation. Я не рекомендую использовать это, потому что обратная анимация мгновенная (вы можете сделать так, чтобы она появлялась постепенно, но это лишняя работа). Проще использовать transition и transform вместе (вышеуказанный подход).

const foo = document.querySelector('.foo')
const bar = document.querySelector('.bar')

bar.addEventListener('click', e => {
  foo.classList.toggle('fadeOutDown')
})
@keyframes fadeOutDown {
  from {}
  to {
    opacity: 0;
    translate: var(--initial-transformX) calc(var(--initial-transformY) + 30px);
  }
}

* {
  box-sizing: border-box;
  font-family: Helvetica;
}

html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
  overflow: hidden;
}

.foo {
  --initial-transformX: -50%;
  --initial-transformY: -10px;
  position: absolute;
  bottom: 0;
  left: 50%;
  width: 40%;
  background: #121212;
  color: white;
  border-radius: 5px;
  padding: 16px;
  text-align: center;
  translate: var(--initial-transformX) var(--initial-transformY);
}

.fadeOutDown {
  animation: .5s ease 0s fadeOutDown forwards;
}

.bar {
  position: absolute;
  top: 50%;
  left: 50%;
  translate: -50% -50%;
  padding: 16px;
  background: #ad17fd;
  color: white;
  border: none;
  cursor: pointer;
  border-radius: 5px;
  transition: all .2s ease;
  text-transform: uppercase;
}
<div class="foo">Hello there, I am foo</div>
<button class="bar">Click me to move foo</button>

Решение # 2

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

const foo = document.querySelector('.foo')
const bar = document.querySelector('.bar')

bar.addEventListener('click', e => {
  foo.classList.toggle('fadeOutDown')
})
* {
  box-sizing: border-box;
  font-family: Helvetica;
}

html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
  overflow: hidden;
}

.wrapper {
  --initial-transformY: -10px;
  position: absolute;
  bottom: 0;
  left: 50%;
  width: 40%;
  color: white;
  text-align: center;
  translate: -50% -10px;
}

.foo {
  width: 100%;
  background: #121212;
  padding: 16px;
  border-radius: 5px;
  transition: translate .5s ease, opacity .5s ease;
}

.fadeOutDown {
  opacity: 0;
  translate: 0px 30px;
}

.bar {
  position: absolute;
  top: 50%;
  left: 50%;
  translate: -50% -50%;
  padding: 16px;
  background: #ad17fd;
  color: white;
  border: none;
  cursor: pointer;
  border-radius: 5px;
  transition: all .2s ease;
  text-transform: uppercase;
}
<div class="wrapper">
  <div class="foo">Hello there, I am foo</div>
</div>
<button class="bar">Click me to move foo</button>
0 голосов
/ 23 апреля 2020

Есть небольшой трюк, который вы можете попробовать, хотя я совершенно уверен, что он сработает для вас. в этом типе элемента по позиции фиксируется не на всех. Проблема, с которой вы столкнулись, связана с тем, что вы используете свойство transform, потому что transform by animate. css перезаписывает ваш код.

вы можете не использовать transform для вашего фиксированного элемента в все. попробуйте что-нибудь подобное, а затем попробуйте исчезнуть.

`#resend_activation_div {
    position:fixed;
    top:100%;
    left:50%;
    margin-top: -10px;
    maergin-left: -(width of your element/2)px; // half of your element.
}` 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...