【问题标题】:css animations end together even though they are started at different timescss 动画一起结束,即使它们是在不同的时间开始的
【发布时间】:2018-06-30 19:41:31
【问题描述】:

我有几个相同类型的元素,我希望它们共享相同的 css 动画,但我希望它们在不同的时间开始/结束动画。

Codepen for the following code

html:

<div class="container">
    <div class="box hidden"></div>
</div>
<div class="container">
    <div class="box hidden"></div>
</div>
<div class="container">
    <div class="box hidden"></div>
</div>

CSS:

.container {
    width: 100px;
    height: 100px;
    margin-bottom: 20px;
}

.box {
    width: 100%;
    height: 100%;
}

.box.hidden {
    visibility: hidden;
}

.box {
    animation: growIn 1s;
    animation-timing-function: cubic-bezier(.46,.13,.99,.83);
    transition: all .2s cubic-bezier(0.215, 0.61, 0.355, 1);
}

.container:first-child .box {
    background-color: green;
}

.container:nth-child(2) .box {
    background-color: orange;
}

.container:nth-child(3) .box {
    background-color: red;
}

@keyframes growIn {
    from {
        transform: scale(0);
    }
    to {
        transform: scale(1);
    }
}

box 元素一开始是隐藏的,然后使用 javascript 我从不同的框中删除了这个类名,但在不同的时间:

const boxes = document.querySelectorAll(".box");
boxes.forEach(box => {
    setTimeout(() => box.classList.remove("hidden"), Math.random() * 1000);
});

发生的情况是所有 3 个框同时结束动画。动画确实在不同的时间开始,但都一起结束。

为什么会这样?
如果我这样做但添加一个类名而不是删除它(为了使动画开始),那么它的行为就像我想要的那样。
有任何想法吗?谢谢。

【问题讨论】:

  • 因为 animation: growIn 1s; 他们都需要 1 秒来制作相同的动画。 jQuery 只控制它们何时开始,但对动画中的 1 秒持续时间没有影响。
  • @SirExotic 这里没有涉及jQuery,是的,它们都有 1 秒的动画持续时间,但我希望第二个动画在每个项目开始时开始,而不是在第一个开始时开始。
  • 抱歉,Javascript*。用于“取消隐藏”框的 Javascript 代码与您的动画同时运行,因此即使您的动画仍在等待您的 Javascript“取消隐藏”框,您的动画也已经开始了。这就是为什么您会看到一些框的大小已经大于 0。
  • @SirExotic 为什么框 2 的动画在 hidden 类名被删除之前开始?为什么框1的动画会影响它?这就是我不明白的。
  • 将你的动画持续时间更改为5s 和 JS 中的 5000,你会看到更好。

标签: css css-animations delay


【解决方案1】:

只是因为所有动画都已经同时开始了。使用visibility:hidden 不会阻止动画开始并使其在元素可见时稍后开始。例如,不透明度也会发生同样的事情:

const boxes = document.querySelectorAll(".box");
boxes.forEach(box => {
  setTimeout(() => box.classList.remove("hidden"), Math.random() * 5000);
});
.container {
  width: 100px;
  height: 100px;
  margin-bottom: 20px;
}

.box {
  width: 100%;
  height: 100%;
}

.box.hidden {
  opacity: 0.1;
}

.box {
  animation: growIn 5s;
  animation-timing-function: cubic-bezier(.46, .13, .99, .83);
  transition: all .2s cubic-bezier(0.215, 0.61, 0.355, 1);
}

.container:first-child .box {
  background-color: green;
}

.container:nth-child(2) .box {
  background-color: orange;
}

.container:nth-child(3) .box {
  background-color: red;
}

@keyframes growIn {
  from {
    transform: scale(0);
  }
  to {
    transform: scale(1);
  }
}
<div class="container">
  <div class="box hidden"></div>
</div>
<div class="container">
  <div class="box hidden"></div>
</div>
<div class="container">
  <div class="box hidden"></div>
</div>

如果您改用 display 属性,您可以看到您正在寻找的行为:

const boxes = document.querySelectorAll(".box");
boxes.forEach(box => {
  setTimeout(() => box.classList.remove("hidden"), Math.random() * 3000);
});
.container {
  width: 100px;
  height: 100px;
  margin-bottom: 20px;
}

.box {
  width: 100%;
  height: 100%;
}

.box.hidden {
  display:none;
}

.box {
  animation: growIn 1s;
  animation-timing-function: cubic-bezier(.46, .13, .99, .83);
  transition: all .2s cubic-bezier(0.215, 0.61, 0.355, 1);
}

.container:first-child .box {
  background-color: green;
}

.container:nth-child(2) .box {
  background-color: orange;
}

.container:nth-child(3) .box {
  background-color: red;
}

@keyframes growIn {
  from {
    transform: scale(0);
  }
  to {
    transform: scale(1);
  }
}
<div class="container">
  <div class="box hidden"></div>
</div>
<div class="container">
  <div class="box hidden"></div>
</div>
<div class="container">
  <div class="box hidden"></div>
</div>

来自specification

'visibility' 属性指定是否由 元素被渲染

不可见的框仍然会影响布局(设置 'display' 属性为 'none' 以完全抑制框生成)。

因此,与使用 display 时不同,使用 visibility 时会始终生成该框。

如果我们检查与动画相关的specification,我们会发现:

将显示属性设置为无将终止任何正在运行的 应用于元素及其后代的动画。如果一个元素 显示为无,将显示更新为无以外的值 将通过动画名称启动应用于元素的所有动画 属性,以及应用于后代的所有动画 显示非无。

【讨论】:

  • 谢谢,改成display: none 成功了。我知道visibilitydisplay 之间的区别,但我不知道它对动画的影响。
  • @NitzanTomer 我还添加了规范的相关部分,清楚地解释了这种行为;)
【解决方案2】:

问题在于您的盒子元素以 .box 类开头,即动画类。这意味着动画从加载元素的那一刻开始,无论它们是否隐藏。这意味着当您删除“隐藏”类时,它们只会在动画期间的某个时刻显露出来。

您要做的是重命名动画类,例如“种植者”

.grower {
    animation: growIn 1s;
    animation-timing-function: cubic-bezier(.46,.13,.99,.83);
    transition: all .2s cubic-bezier(0.215, 0.61, 0.355, 1);
}

然后在 javascript 循环中有这个:

const boxes = document.querySelectorAll(".box");
boxes.forEach(box => {
  setTimeout(() => {
    box.classList.remove("hidden");
    box.classList.add("grower"); }, Math.random() * 1000);
});

这里有一个 sn-p 来展示它的实际效果:

const boxes = document.querySelectorAll(".box");
boxes.forEach(box => {
  setTimeout(() => {
    box.classList.remove("hidden");
    box.classList.add("grower"); }, Math.random() * 1000);
});
.container {
  width: 100px;
  height: 100px;
  margin-bottom: 20px;
}

.box {
  width: 100%;
  height: 100%;
}

.box.hidden {
  visibility: hidden;
}

.grower {
	animation: growIn 1s;
	animation-timing-function: cubic-bezier(.46,.13,.99,.83);
	transition: all .2s cubic-bezier(0.215, 0.61, 0.355, 1);
}

.container:first-child .box {
  background-color: green;
}

.container:nth-child(2) .box {
  background-color: orange;
}

.container:nth-child(3) .box {
  background-color: red;
}

@keyframes growIn {
  from {
		transform: scale(0);
  }
  to {
		transform: scale(1);
  }
}
<div class="container">
  <div class="box hidden"></div>
</div>
<div class="container">
  <div class="box hidden"></div>
</div>
<div class="container">
  <div class="box hidden"></div>
</div>

【讨论】:

  • 谢谢,我知道添加一个类名(即grower)是可以做到的,但我想避免它,因为我以后需要在动画结束时删除这个类名,因为我不再需要它了。
猜你喜欢
  • 2016-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 2016-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多