【问题标题】:CSS animation creates flickering "bounding box" when animating paddingCSS 动画在填充动画时会创建闪烁的“边界框”
【发布时间】:2015-11-26 04:20:47
【问题描述】:

我正在尝试为圆形 div 设置动画以提供类似波纹的效果,填充它的容器。应该有一个初始波纹(边框),然后是主要形状扩展以填充容器。

我通过将圆形 div 的边框宽度与填充相结合来实现波纹,从而将边框向外推。

问题是,当填充动画时,圆形 div 的边界框会闪烁白色。如果我删除动画的填充部分,只为边框宽度设置动画,则不会出现闪烁,所以我知道是填充导致了问题。

@keyframes circle {
0% {
    width:0.001px;
    border-width:0px;
    padding:0px;
}
50% {
    width:0.001px;
    border-width:100px;
    padding:400px;
}
100% {
    width:125%;
    border-width:100px;
    padding:400px;
}
}

Here's a fiddle 进行演示。点击灰色框将其激活。

编辑:在 Firefox 中进行测试后,它按预期工作。可能是特定于 webkit 的?

编辑 2:我见过的用于修复通用“动画期间闪烁”错误的 2 个常见解决方案是添加样式

-webkit-transform-style: preserve-3d;

-webkit-backface-visibility: hidden;

到有问题的元素。这些我都试过了,都没有解决。

最初,我使用多个圆形 div 和一系列带有转换的类(表示动画的各种状态)来完成这个动画,然后使用 setInterval 延迟触发这些类。现在我对 CSS 动画更加熟悉了,我正在尝试对其进行重新编码,使其对 CPU 更友好,因为旧方法在旧笔记本电脑上一直存在。我假设单个圆形 div 与多个圆形 div 相比,调用单个动画而不是不断添加和删除类会更有效?

【问题讨论】:

  • 当我点击灰色框时,我什么也没有发生。我正在使用火狐。
  • @RohitGupta 他正在使用 webkit 属性。它可能仅适用于 Chrome 和 Safari。
  • @RohitGupta 正如 Manoj 提到的,我使用的是 webkit 属性,但也更新了 fiddle 以在 Firefox 上工作。我从 Firefox 中的测试中注意到没有问题,因此这可能是特定于 webkit 的问题。

标签: jquery css webkit css-animations


【解决方案1】:

错误原因

webkit 错误与动画填充有关(如您所述)。在本例中,我将 paddings 角色替换为宽度和高度。

其他变化

  • 点击动画时添加一个类,然后删除该类。这样动画就可以反复重复使用。

  • 我更改了关键帧,以便在动画结束时,白色慢慢变透明。

前缀说明

示例 1

根据自己的喜好调整,边框与背景位于同一元素上,因此它们会同时移动。

$("#circleCont").click(function() {
  $(".circle").addClass('animated');
  setTimeout(function() {
    $(".circle").removeClass('animated');
  }, 4000);
});
.circle {
  position: absolute;
  top: 50%;
  left: 50%;
  margin: auto;
  border: 0 solid #FFF;
  display: block;
  border-radius: 50%;
  background-color: white;
  background-clip: content-box;
  transform: translate(-50%, -50%);
  z-index: 2;
}
#circleCont {
  display: inline-block;
  position: absolute;
  width: 100%;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  box-shadow: inset 0px 0px 0px 0px rgba(0, 0, 0, 0);
  transition: box-shadow 0.1s;
}
#circleCont:after {
  content: '';
  display: block;
  margin-top: 100%;
}
#hero {
  width: 600px;
  height: 400px;
  background-color: #ddd;
  position: absolute;
  overflow: hidden;
}
.animated {
  animation: circle 4s forwards
}
@keyframes circle {
  0% {
    width: 0;
    border-width: 0px;
    height: 0;
  }
  25% {
    border-width: 100px;
    width: 400px;
    height: 400px;
  }
  50% {
    height: 800px;
    width: 800px;
    border-width: 100px;
    padding: 400px;
    background: #FFF;
  }
  100% {
    height: 800px;
    width: 800px;
    border-width: 100px;
    padding: 400px;
    background: transparent;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="hero">
  <div id="circleCont">
    <div class="circle"></div>
  </div>
</div>

示例 2

在此示例中,边框设置在不同的元素上。背景元素被赋予一个animation-delay,以便它在边框动画之后稍微开始。

$("#circleCont").click(function() {
  $('.circle').addClass('animated');
  $('.border').addClass('animated');
  setTimeout(function() {
    $('.circle').removeClass('animated');
    $('.border').removeClass('animated');
  }, 4500);
});
.circle {
  position: absolute;
  top: 50%;
  left: 50%;
  margin: auto;
  overflow: hidden;
  display: block;
  border-radius: 50%;
  background-color: white;
  transform: translate(-50%, -50%);
  z-index: 2;
}
.border {
  position: absolute;
  top: 50%;
  left: 50%;
  margin: auto;
  overflow: hidden;
  display: block;
  border-radius: 50%;
  background-color: transparent;
  transform: translate(-50%, -50%);
  z-index: 2;
  border: solid 100px transparent;
}
#circleCont {
  display: inline-block;
  position: absolute;
  width: 100%;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  box-shadow: inset 0px 0px 0px 0px rgba(0, 0, 0, 0);
  transition: box-shadow 0.1s;
}
#circleCont:after {
  content: '';
  display: block;
  margin-top: 100%;
}
#hero {
  width: 600px;
  height: 400px;
  background-color: #ddd;
  position: absolute;
  overflow: hidden;
}
.circle.animated {
  animation: circle 4s forwards;
  animation-delay: .5s;
}
.border.animated {
  animation: circle 4s forwards;
  animation-delay: 0;
}
@keyframes circle {
  0% {
    width: 0;
    height: 0;
    border-color: #FFF;
  }
  50% {
    height: 800px;
    width: 800px;
    background: #FFF;
    border-color: #FFF;
  }
  100% {
    height: 800px;
    width: 800px;
    border-color: #FFF;
    background: transparent;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="hero">
  <div id="circleCont">
    <div class="circle"></div>
    <div class="border"></div>
  </div>
</div>

【讨论】:

  • 我明白了……这似乎可行,但对于我的生活,我不明白为什么?如果不是您示例中的填充,是什么将边框推离圆圈的主体?我似乎无法分解它是如何工作的,特别是因为我已经在我的代码中使用了宽度和高度,但是你对它的使用似乎以某种方式修复了这个错误。您介意解释一下您是如何得出这个解决方案的吗?
  • 同样,我想延迟主圈的增长,使其不会与涟漪同时开始。我在这里尝试过这样做,但是如果 2 没有同时增长,则闪烁会返回。 jsfiddle.net/x8f0qby8/7
  • 关于它的工作原理:See this example。第一个 div 没有高度或宽度,只有填充(顶部、右侧、底部和左侧各 100 像素的填充)。第二个 div 的高度和宽度为 200px,占用相同的空间。当它们为空时,外观相同。
  • 查看我的编辑。示例 2 有一个单独的元素用于边框波纹。这样我们就可以延迟主圈动画的开始。它必须是一个单独的元素才能工作。
猜你喜欢
  • 2016-05-24
  • 2012-07-10
  • 1970-01-01
  • 2014-06-16
  • 2019-04-15
  • 2017-09-15
  • 1970-01-01
  • 2020-08-28
相关资源
最近更新 更多