是否可以将 animate.css 用于已翻译的元素?

Is it possible to use animate.css with already translated elements?

我在网站上使用 Daniel Eden's animate.css。它工作得很好,但我在处理已经应用了 transform:translate() 的元素时遇到了问题。

我遇到的问题:

我有一个固定在页面底部的 div,在 x 方向上变换了 -50%,在 y 方向上稍微超过 -100% 以使其居中:

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

看起来像这样:

我在单击 X 时将 animated fadeOutDown 添加到 divclassList。我希望该元素从其在页面上的位置直接向下淡出。问题是,动画按以下方式工作...

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

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

...所以我原来的变换规则被覆盖了,元素按照上图中蓝色箭头的方向淡出。

我的解决方法:

到目前为止,我发现克服这个问题的唯一方法是定义一个新的 class,其中包含我想要的翻译,然后在 classList 中使用它......

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

...这有效,但这意味着为我对元素进行的每个不同变换的每个动画编写一个新规则!

所以我的问题是:有没有更聪明的方法来做到这一点?我可以在动画规则中执行转换时让 css 尊重我的原始转换吗?

说明

不幸的是,CSS 无法在未被明确告知的情况下知道元素先前具有的 transform 值。话虽如此,您的问题有一个解决方法:只需明确告诉 CSS 初始 transform 值。

要使用纯 CSS 实现您想要的效果,我们可以使用 calc function to perform calculations. Along with calc, we will also be using CSS custom properties 显式声明初始转换值 。然后,还告诉 CSS 执行淡出动画所需的 translateY 的值(例如 30px)。由于 calc 可用于对 CSS 自定义属性进行操作,因此我们现在可以计算出我们想要的最终 translate 值(例如 translate: 0px calc(var(--initial-transformY) + var(--added-transformY)))。将所有这些操作放在 class 中(例如 .fadeOutDown),我们现在可以简单地将此 class 添加到您想要淡出的任何元素。


解决方案 #1

这里有一个示例,展示了如何结合使用 CSS 自定义属性和 calc 来实现您想要的效果。在此示例中,您可以简单地向要淡出的元素添加 fadeOutDown class(无需使用 animation 属性)。 class 会将 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 属性 的示例。我不鼓励使用这个,因为反向动画是即时的(你可以让它逐渐出现,但这是额外的工作)。一起使用 transitiontransform 更容易(上述方法)。

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>

有一个小技巧你可以试试,虽然我很确定它对你有用。在这种类型的元素中,位置是固定的,而不是全部。 您遇到的问题是因为您使用了转换 属性,因为 animate.css 的转换覆盖了您的代码。

您可以做的就是根本不要对固定元素使用变换。尝试这样的事情,然后尝试淡出。

`#resend_activation_div {
    position:fixed;
    top:100%;
    left:50%;
    margin-top: -10px;
    maergin-left: -(width of your element/2)px; // half of your element.
}`