Safari忽略关键帧动画的内联样式

时间:2020-07-29 16:41:47

标签: css safari inline keyframe programmatically-created

在仅使用末尾帧的Safari(台式机和iOS)中使用CSS @keyframes设置transform并通过编程方式(通过JS内联)以编程方式更新起始transform的位置时,出现Safari继续从初始位置开始执行动画(即使用样式表中的初始转换值)-不使用内联样式。

简而言之,Safari关键帧动画似乎没有更新以反映以编程方式添加的内联样式的任何更改

下面的代码段(简化的测试用例)在Firefox和Chrome中均可使用,但是Safari只是将动画设置为0位置。我的问题是是否有解决方法?这是Apple规格的预期代表吗?对于关键帧动画,应该忽略编程内联样式吗?我无法想象他们应该这样做。

我尝试克隆和替换元素,但无济于事。我还测试了onLoad包含的内联样式,并且 did 在Safari中可以正常工作,因此该错误似乎仅在以编程方式添加该样式时出现。

我很高兴可以完全使用JS和requestAnimationFrame制作动画,如果以上方法失败,这是我的后备解决方案。 (同样,一个很好的解决方案是使用Web Animation API,它似乎正是为此目的而制作的。但是对此的支持是零散的,因此暂时不做。)我真正感兴趣的是解决上述错误的方法,而不是其他建议。

(顺便说一句,<marquee>标签仍然可以作为跨浏览器的解决方案... * shudder *)

// Get slides
let marquee = document.querySelector('.mock-marquee__content');

// Transform slides for initial offset
marquee.style.transform = `translate(-${marquee.clientWidth}px, 0)`;
.mock-marquee {
  overflow: hidden;
  display: flex;
}
.mock-marquee__content {
  white-space: nowrap;
  display: flex;
  animation: marquee 5s linear infinite;
}
.mock-marquee__content__slide {
  display: block;
}
.mock-marquee__content__slide:not(:first-child) {
  margin-left: 100px;
}
.mock-marquee__content:hover {
  animation-play-state: paused;
}

@keyframes marquee {
  from {
    transform: translate(100vw, 0);
  }
}
<div class="mock-marquee">
  <div class="mock-marquee__content">
    <span class="mock-marquee__content__slide">Hello</span>
    <span class="mock-marquee__content__slide">world</span>
    <span class="mock-marquee__content__slide">Foo</span>
    <span class="mock-marquee__content__slide">Bar</span>
    <span class="mock-marquee__content__slide">Bat</span>
    <span class="mock-marquee__content__slide">Another one</span>
    <span class="mock-marquee__content__slide">And another! Wowz</span>
  </div>
</div>

1 个答案:

答案 0 :(得分:0)

解决了!解决方案只是使用setTimeout在删除/添加节点时强制排队。像这样:

window.addEventListener('load', () => {
  let marqueeWrapper = marquee.parentNode;

  // Remove marquee
  marquee.remove();

  // Re-add, with forced queuing
  setTimeout(() => {
    marqueeWrapper.append(marquee);
  }, 0)
})

这迫使Safari完全重新渲染该节点,并似乎解决了该问题