【问题标题】:HTML + CSS infinite scrolling background: Flicker on Safari at repeatHTML + CSS 无限滚动背景:Safari 上重复闪烁
【发布时间】:2021-05-21 17:37:40
【问题描述】:

我正在创建一个带有一堆滚动层(前景、中景、背景等)的场景,但令人讨厌的是,当动画重新启动时,我在 Safari (14.0.3) 上出现闪烁。这不会在 Chrome 或 Firefox 上发生。

我在这里创建了一个最小的可重现示例:

https://brendon.github.io/safari_flicker/index.html

代码如下:

.animation {
  position: relative;
  height: 395px;
  background-image: linear-gradient(#1b9dd9, #00b6ed 44%, #ffe56c 75%);
}

.animation .scrollingAnimation {
  position: absolute;
  overflow: hidden;
  height: 100%;
  width: 100%;
}

.animation .scrollingAnimation:before {
  content: "";
  position: absolute;
  height: 100%;
  width: 200%;
}

.animation .foreground:before {
  /* Dimensions: */
  /* width: 1696px; */
  /* height: 74px; */
  min-width: 6784px;
  background-image: url("https://brendon.github.io/safari_flicker/foreground.png");
  background-position: left bottom -11px;
  background-repeat: repeat-x;
  background-size: auto 74px;
  transform: translateX(-1696px);
  animation: foreground 10s linear infinite;
}

@keyframes foreground {
  0% {
    transform: translateX(-1696px);
  }
  to {
    transform: translateX(-3392px);
  }
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>

  <div class="animation">
    <div class="foreground scrollingAnimation"></div>
  </div>

</body>

</html>

这是该问题的视频:

https://github.com/brendon/safari_flicker/raw/main/flicker_video.mp4

我已经尝试了很多方法来解决这个问题。根据窗口宽度,它似乎有时会消失,但我正在寻找一个可靠的解决方案:D

iOS Safari 也存在此问题。

我应该提一下,我不想为 background-position 属性设置动画,因为这会导致性能问题并且不会被 GPU 加速。

【问题讨论】:

标签: html css safari


【解决方案1】:

您是否考虑过使用具有相同图像和动画的 2 个元素,并偏移 - 使用延迟 - -duration / 2 的第一个元素动画?

这个想法是,屏幕上始终有一个,并且任何渲染延迟都不应该是可见的。

见下文,我正在为两个伪元素设置动画。

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

.animation, .foreground {
  height: 100%;
  width: 100%;
  background: black;
}

.foreground:before, .foreground:after {
  height: 100%;
  width: 200%;
  
  position: absolute;
  top: 0;
  
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 50vmin;
}

.foreground {
  position: relative;
  overflow-x: hidden;
}

.foreground:before {
  content: 'A';
  background: red;
  
  animation: 10s linear -5s infinite foreground;
}

.foreground:after {
  content: 'B';
  background: blue;
  
  animation: 10s linear 0s infinite foreground;
}

@keyframes foreground {
  0% {
    transform: translateX(100%);
  }
  to {
    transform: translateX(-100%);
  }
}
<div class="animation">
    <div class="foreground scrollingAnimation"></div>
  </div>

【讨论】:

  • 这听起来像是一个积极的方向。就在我开始尝试之前,这会在非常宽的屏幕上引起问题吗?我认为可能不会,只要这两个元素的宽度至少为 100% 并且它们的背景图像重复。
  • @BrendonMuir 是的,我打算进行编辑以将其添加为警告。如果您可以保证元素在重新启动动画循环时完全不在屏幕上,它只会解决您的问题。在这种情况下,只要动画元素的宽度超过容器的 100% 就可以了。
  • 鉴于它是一种重复模式,它需要至少与容器一样宽 100%,而且是图像宽度的倍数。
  • @BrendonMuir 图像使它更复杂,但您可以将其隔离为元素而不是动画的问题。 TranslateX 百分比适用于元素宽度(而不是容器宽度),因此如果元素宽度是图像宽度的精确倍数,则动画会自行处理。您必须决定要支持的最大屏幕宽度,并让您的元素宽度大于此值。
  • 为每个不同的图层(前景、中景等)赋予其自己的命名动画(即使它们相同)似乎可以解决间隙问题。很奇怪!我明天会做一些测试,但我认为你的解决方案有效:)
【解决方案2】:

我最终使用 GSAP fromTo() 来管理过渡工作,而不是依赖 CSS 动画:

<div class="foreground scrollingAnimation"><div></div></div>
gsap.fromTo(
  '.foreground > div',
  { xPercent: -25 },
  { xPercent: -50, duration: 10, repeat: -1, ease: 'none' }
)
.scrollingAnimation {
  position: absolute;
  overflow: hidden;
  height: 100%;
  width: 100%;

  > div {
    position: absolute;
    height: 100%;
  }
}

.foreground {
  > div {
    width: calc(1696px * 4);

    background: {
      image: url("https://brendon.github.io/safari_flicker/foreground.png");
      position: left bottom;
      repeat: repeat-x;
      size: auto 74px;
    }
  }
}

它在非常宽的屏幕上会出现故障,但实际上,如果您正在摇晃 6000 像素宽的窗口,那么祝您好运。

GSAP 动画的方式是它在 requestAnimationFrame 期间通过 javascript 更改 translateX 值(我认为),因此它非常流畅,并且在这种情况下不存在闪烁问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-21
    • 1970-01-01
    • 2020-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多