Как оптимизировать анимации CSS (масштабирование, поворот, размытие)

Следующий пример HTML состоит из двух изображений; один фон, другой - объект. Оба анимируются с помощью масштабирования и вращения. На полноэкранных мониторах он имеет тенденцию быть неспокойным. Когда вы смотрите на производительность в Firefox, она получает около 20 кадров в секунду.

Сначала я использовал jQuery; для повышения производительности я выбрал CSS, но он все еще не идеален. Чтобы воспроизвести проблему, перейдите в полноэкранный режим. Как я могу сделать это лучше?

.html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background-color: #121212;
}

.maincontainer {
  width: 100%;
  padding-bottom: 100%;
  position: fixed;
  overflow: hidden;
}

.bg {
  background-image: url(http://wallpaper-gallery.net/images/beautiful-pictures-of-nature/beautiful-pictures-of-nature-2.jpg);
  height: 100%;
  width: 100%;
  display: block;
  position: absolute;
  z-index: -99;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  background-position: top;
  background-size: 100% auto;
  background-repeat: no-repeat;
}

.bg2 {
  height: 100%;
  width: 100%;
  display: block;
  position: absolute;
  z-index: -99;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  background-position: top;
  background-size: 100% auto;
  background-repeat: no-repeat;
}

.rain {
  background-image: url(https://media.giphy.com/media/OvFQrZk8b5N0Q/source.gif);
  height: 100%;
  width: 100%;
  display: block;
  position: absolute;
  z-index: -1;
  -webkit-filter: blur(1px);
}

.animate-bg {
  -webkit-animation-name: animateBg;
  animation-name: animateBg;
}

.animate {
  -webkit-animation-duration: 35000;
  animation-duration: 35000ms;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
  -webkit-animation-timing-function: cubic-bezier(.3, 0, .7, 1);
  animation-timing-function: cubic-bezier(.3, 0, .7, 1);
  animation-iteration-count: infinite;
}


/* Zoom in Keyframes */

@-webkit-keyframes animateBg {
  0% {
    transform: scale(1) rotate(0deg);
  }
  50% {
    transform: scale(1.3) rotate(4deg);
  }
  100% {
    transform: scale(1) rotate(0deg);
  }
}

@keyframes animateBg {
  0% {
    transform: scale(1) rotate(0deg);
  }
  50% {
    transform: scale(1.3) rotate(4deg);
  }
  100% {
    transform: scale(1) rotate(0deg);
  }
}


/*End of Zoom in Keyframes */

.eagle {
  background-image: url(http://www.pngmart.com/files/1/Flying-Eagle-PNG-Image.png);
  height: 100%;
  width: 100%;
  display: block;
  position: absolute;
  z-index: 900;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  background-position: top;
  background-size: 100% auto;
  background-repeat: no-repeat;
}

.animate-eagle {
  -webkit-animation-duration: 35000;
  animation-duration: 35000ms;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
  -webkit-animation-timing-function: cubic-bezier(.3, 0, .7, 1);
  animation-timing-function: cubic-bezier(.3, 0, .7, 1);
  animation-iteration-count: infinite;
  -webkit-animation-name: animateeagle;
  animation-name: animateeagle;
}


/* Zoom in Keyframes */

@-webkit-keyframes animateeagle {
  0% {
    transform: scale(0.8) rotate(0deg);
  }
  30% {
    transform: scale(1.05) rotate(-2deg);
  }
  50% {
    transform: scale(1.1) rotate(0deg);
  }
  80% {
    transform: scale(1.05) rotate(2deg);
  }
  100% {
    transform: scale(1) rotate(0deg);
  }
}

@keyframes animateeagle {
  0% {
    transform: scale(1) rotate(0deg);
  }
  30% {
    transform: scale(1.05) rotate(-2deg);
  }
  50% {
    transform: scale(1.1) rotate(0deg);
  }
  80% {
    transform: scale(1.05) rotate(2deg);
  }
  100% {
    transform: scale(1) rotate(0deg);
  }
}


/*End of Zoom in Keyframes */

.blur {
  animation: blur 5000ms;
}

@keyframes blur {
  0% {
    -webkit-filter: blur(0px);
  }
  20% {
    -webkit-filter: blur(3px);
  }
  40% {
    -webkit-filter: blur(5px);
  }
  60% {
    -webkit-filter: blur(7px);
  }
  80% {
    -webkit-filter: blur(5px);
  }
  100% {
    -webkit-filter: blur(0px);
  }
}

@-webkit-keyframes blur {
  0% {
    -webkit-filter: blur(0px);
  }
  20% {
    -webkit-filter: blur(3px);
  }
  40% {
    -webkit-filter: blur(5px);
  }
  60% {
    -webkit-filter: blur(7px);
  }
  80% {
    -webkit-filter: blur(5px);
  }
  100% {
    -webkit-filter: blur(0px);
  }
}

.unblur {
  animation: unblur 1000ms;
}

@keyframes unblur {
  0% {
    -webkit-filter: blur(5px);
  }
  100% {
    -webkit-filter: blur(0px);
  }
}

@-webkit-keyframes unblur {
  0% {
    -webkit-filter: blur(5px);
  }
  100% {
    -webkit-filter: blur(0px);
  }
}
<div class="maincontainer">

  <div id="bg2" class="bg2">
    <div id="bg" class="bg animate animate-bg">
      <div class="rain"></div>
      <div class="drops"></div>
    </div>
  </div>

  <div id="eagle">
    <div class="eagle animate-eagle">
    </div>
  </div>
</div>

Ответ 1

Посмотрите на атрибут will-change, возможно, это может помочь вам немного разобраться, вы можете прочитать об этом здесь

у него нет наибольшей поддержки браузера, это единственное.

Я подозреваю, что ваше размытие 1px на дождь, вероятно, довольно интенсивно, вы размываете то, что постоянно меняется. Я не могу понять, где вы используете класс .blur и связанную с ним анимацию, но это будет довольно дорого для производительности.

transform: translate3d(0,0,0);, как предлагает Роберт Мур, помогает webkit, в частности, использовать аппаратное ускорение, вы можете прочитать об этом здесь, однако в этом случае, поскольку вы используют фильтры, которые уже используют аппаратное ускорение

Ответ 2

Это потому, что вы размываете анимированный GIF в реальном времени.

Удалите -webkit-filter: blur(1px);, и отставание исчезло.

Я попытался воссоздать эффект дождь с элементом холста, но получил тот же результат, поэтому GIF здесь не проблема.

Проблема в том, что Firefox, похоже, борется с фильтром размытия на анимированных элементах.

(Не совсем ответ, но слишком длинный для комментария)