iOS Safari / Chrome / Firefox中的CSS关键帧动画闪烁/不同步

时间:2018-05-19 19:55:04

标签: ios reactjs css-animations keyframe

我有一个带有CSS关键帧动画的React应用程序来更改文本的外观,并使用setState和setInterval通过JS动态更改字体。

我同步关键帧动画以便在调用setInterval的同时开始播放,并且Chrome / Safari桌面上的一切正常。在iOS上的Safari / Chrome / Firefox上,动画闪烁,并且通常不同步。有趣的是,在Safari上如果我在初始加载后刷新页面,一切都会正常工作。

我已经在这里阅读了许多类似问题的主题,但没有一个解决方案适合我。我尝试添加-webkit-backface-visibility: hidden;body {-webkit-transform:translate3d(0,0,0);},并尝试在动画开头添加延迟以抵消闪烁。没有任何效果。

以下是实时链接:https://stoic-khorana-e0bd2c.netlify.com/

这是代码 - 它是一个小应用程序,基本上只是一个启动页面:https://github.com/themarquisdesheric/el4d/tree/master/src

我延迟了“AKA'显示,然后另一个延迟的名称改变开始。

SCSS:

.aka-container {
  .aka { 
    opacity: 0;
    animation: showAKA 400ms 750ms ease-out forwards;
  }

  .name-changer {
    animation: fade 1500ms infinite paused; 

    &.playing { animation-play-state: running; }
  }

}

@keyframes showAKA {
  20%,
  100% { opacity: 1; }
}

@keyframes fade {
  0% { opacity: 0; }
  20%,
  80% { opacity: 1; }
  100% { opacity: 0; }
}

这是React组件:

class NameChanger extends Component {
  state = {
    name: null,
    fontFamily: null,
    index: 0,
    playing: false
  };

  componentDidMount() {
    window.setInterval(this.changeName, 1500);
    this.setState({ playing: true });
  }

  changeFont = (index) => {
    switch (index) {
      case 0:
        return 'Sedgwick Ave Display';
      case 1:
        return 'Bangers';
      case 2:
        return 'Luckiest Guy';
      default:
        return 'Bangers';
    }
  };

  changeName = () => {
    const names = ['ol lightsy', 'eladi-da', 'el-40'];
    const { index } = this.state;
    const { changeFont } = this;

    this.setState(prevState => ({
      name: names[index],
      fontFamily: changeFont(index),
      index: (index === names.length - 1) 
        ? 0 
        : prevState.index + 1
    }));
  };

  render() {
    const { name, fontFamily, playing } = this.state;

    return (
      <span
        className={`name-changer ${playing ? 'playing' : ''}`} 
        style={{ 
          fontFamily,
          position: 'relative',
          top: (name === 'el-40') ? '.25rem' : ''
        }}
      >
        {name}
      </span>
    );
  }
}

我想知道为什么这在Chrome中运行良好,但在移动设备上有问题。预先感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

如果它认为页面正在滚动/缩放,则证明iOS pauses timers。这适用于iOS上的Safari,Chrome和Firefox。

我通过删除使用setInterval并使用animationiteration事件实现相同效果来解决此问题。显然,动画自己的计时器是受到尊重的,而像setInterval这样的计时器则不然。

class NameChanger extends Component {
  state = {
    name: null,
    fontFamily: null,
    index: 0,
    playing: false
  };

  componentDidMount() {
    const { span, changeName } = this;

    span.addEventListener('animationiteration', 
      () => changeName()
    );

    this.setState({ playing: true });
  }

  changeFont = (index) => {
    switch (index) {
      case 0:
        return 'Sedgwick Ave Display';
      case 1:
        return 'Bangers';
      case 2:
        return 'Luckiest Guy';
      default:
        return 'Bangers';
    }
  };

  changeName = () => {
    const names = ['ol lightsy', 'eladi-da', 'el-40', 'elautopilot'];
    const { index } = this.state;
    const { changeFont } = this;

    this.setState(prevState => ({
      name: names[index],
      fontFamily: changeFont(index),
      index: (index === names.length - 1) 
        ? 0 
        : prevState.index + 1
    }));
  };

  render() {
    const { name, fontFamily, playing } = this.state;

    return (
      <span
        className={`name-changer ${playing ? 'playing' : ''}`} 
        ref={span => this.span = span}
        style={{ 
          fontFamily,
          position: 'relative',
          top: (name === 'el-40') ? '.25rem' : ''
        }}
      >
        {name}
      </span>
    );
  }
}