Как синхронизировать c две анимации, используя css ключевые кадры? - PullRequest
6 голосов
/ 26 марта 2020

Я работаю над решением

Я создал базовый баннер c html, в котором хочу синхронизировать изображения и текстовую анимацию c.

В основном анимация изображения примерно как масштаб lo go в течение примерно 3 секунд, в то время как lo go анимирован. Я хочу текст для того же эффекта печати

Я создал решение basi c с использованием css и javascript, но оно не синхронизировано c

var typewriter = function(txt) {
  var container = document.getElementById('typewriter'),
    speed = 28,
    i = 0,
    wordsObj = txt.split(" ")
  container.textContent = "";
  runAllWords();

  function runAllWords() {

    if (i < wordsObj.length) {
      var a = (i == 0) ? i : i - 1;
      setTimeout(function() {
        showWord(wordsObj[i], 0)
      }, wordsObj[a].length * speed);
    }
  }

  function showWord(word, countWord) {
    if (countWord < word.length) {
      setTimeout(function() {
        showLetter(word, countWord)
      }, speed);
    } else {
      container.textContent = container.textContent + " ";
      i += 1;
      runAllWords();
    }
    if (i === wordsObj.length) {
      console.log('complete')
    }
  }

  function showLetter(word, countWord) {
    container.textContent = container.textContent + word[countWord];
    showWord(word, countWord + 1);
  }
}

var i = 0;

function myLoop() {
  //  create a loop function

  var dataType = document.getElementById('typewriter').dataset.typewriter,
    w = dataType.split(',')
  setTimeout(function() { //  call a 3s setTimeout when the loop is called
    typewriter(w[i]); //  your code here
    i++; //  increment the counter
    if (i < w.length) { //  if the counter < 10, call the loop function
      myLoop(); //  ..  again which will trigger another 
    } //  ..  setTimeout()
  }, 3000)
}

myLoop();
.addsp_320x50 {
  width: 100%;
  height: 50px;
  position: relative;
}

.addsp_320x50_img {
  position: absolute;
  top: 1px;
  left: 10px;
  width: 48px;
  height: 48px;
  border: 0px solid #ccc;
  border-radius: 50%;
}

.addsp_title_text {
  position: absolute;
  top: 5px;
  left: 70px;
  font-family: Open Sans;
  font-weight: bold;
}

.addsp_title_desc {
  position: absolute;
  top: 20px;
  left: 70px;
  font-family: Open Sans;
  color: #999;
}

.addsp_320x50_action button {
  height: 27px;
  background: #058562;
  border-radius: 4px;
  color: #fff;
  border-color: #058562;
  font-size: 12px;
  font-weight: bold;
  font-family: Open Sans;
  border-style: solid;
  position: absolute;
  right: 10px;
  top: 10px;
  display: flex;
}

.adz_text_1 {}

.adz_text_2 {
  animation: text2;
}

.adz_text_1,
.adz_text_2 {}

@keyframes text2 {
  0%,
  50%,
  100% {
    width: 0px;
  }
  60%,
  90% {
    width: 200px;
  }
}

@keyframes text1 {
  0%,
  50%,
  100% {
    width: 0px;
  }
  10%,
  40% {
    width: 200px;
  }
}

@media only screen and (min-width: 320px) {
  .addsp_320x50_img {
    width: 42px;
    height: 42px;
    top: 4px;
    left: 5px;
  }
  .addsp_title_text {
    top: 14px;
    left: 56px;
    font-size: 0.85rem;
  }
  .addsp_title_desc {
    top: 25px;
    left: 55px;
    font-size: 0.8rem;
  }
}

@media only screen and (min-width: 480px) {
  .addsp_title_text {
    top: 3px;
    left: 55px;
    font-size: 1.1rem;
  }
  .addsp_title_desc {
    top: 28px;
    left: 55px;
    font-size: 0.8rem;
  }
}

@media only screen and (min-width: 600px) {
  .addsp_title_text {
    top: 3px;
    left: 70px;
    font-size: 1.1rem;
  }
  .addsp_title_desc {
    top: 28px;
    left: 70px;
    font-size: 0.8rem;
  }
}

@media only screen and (min-width: 800px) {
  .addsp_title_text {
    top: 3px;
    left: 70px;
    font-size: 1.1rem;
  }
  .addsp_title_desc {
    top: 28px;
    left: 70px;
    font-size: 0.8rem;
  }
}

.addsp_320x50_img:nth-child(1) {
  animation-name: scale;
  animation-duration: 3s;
  animation-timing-function: linear;
  animation-delay: 1s;
  animation-iteration-count: infinite;
  animation-fill-mode: forwards;
  opacity: 0;
}

.addsp_320x50_img:nth-child(2) {
  animation-name: scale;
  animation-duration: 3s;
  animation-timing-function: linear;
  animation-delay: 4s;
  animation-iteration-count: infinite;
  animation-fill-mode: forwards;
  opacity: 0;
}

.addsp_320x50_img:nth-child(3) {
  animation-name: scale;
  animation-duration: 3s;
  animation-timing-function: linear;
  animation-delay: 7s;
  animation-iteration-count: infinite;
  animation-fill-mode: forwards;
  opacity: 0;
}

@keyframes scale {
  0% {
    transform: scale(1);
    opacity: 1
  }
  20% {
    transform: scale(1.2);
    opacity: 1
  }
  40% {
    transform: scale(1);
    opacity: 1
  }
  60% {
    transform: scale(1.2);
    opacity: 1
  }
  80% {
    transform: scale(1);
    opacity: 1
  }
  90% {
    transform: translateY(-100px);
    opacity: 0;
  }
  100% {
    opacity: 0;
  }
}

.blinking-cursor {
  color: #2E3D48;
  -webkit-animation: 1s blink step-end infinite;
  -moz-animation: 1s blink step-end infinite;
  -ms-animation: 1s blink step-end infinite;
  -o-animation: 1s blink step-end infinite;
  animation: 1s blink step-end infinite;
}

@keyframes "blink" {
  from,
  to {
    color: transparent;
  }
  50% {
    color: black;
  }
}

@-moz-keyframes blink {
  from,
  to {
    color: transparent;
  }
  50% {
    color: black;
  }
}

@-webkit-keyframes "blink" {
  from,
  to {
    color: transparent;
  }
  50% {
    color: black;
  }
}

@-ms-keyframes "blink" {
  from,
  to {
    color: transparent;
  }
  50% {
    color: black;
  }
}

@-o-keyframes "blink" {
  from,
  to {
    color: transparent;
  }
  50% {
    color: black;
  }
}
<div class="addsp_320x50">
  <img src="https://de7yjjf51n4cm.cloudfront.net/banners/amazonprime_newicon.jpg" class="addsp_320x50_img">
  <img src="https://de7yjjf51n4cm.cloudfront.net/banners/amazonprime_newicon.jpg" class="addsp_320x50_img">
  <img src="https://de7yjjf51n4cm.cloudfront.net/banners/amazonprime_newicon.jpg" class="addsp_320x50_img">
  <div class="addsp_title_text">
    <span class="adz_text_1 typewriter" id="typewriter" data-typewriter="Web Strategy,
    		UX Testing,
    		Content Management System,
    		Web Design,
    		Research and Analytics,
    		Information Architecture,
    		Strategic Consulting,Maintenance and Support"></span><span class="blinking-cursor">|</span>
  </div>
  <div class="addsp_320x50_action">
    <button>DOWNLOAD</button></div>
</div>

Ответы [ 3 ]

2 голосов
/ 03 апреля 2020

Говоря математически, погружение означает настройку частоты и фазы. Я продемонстрирую каждый в отдельности. Обратите внимание, что я собираюсь объяснить концепцию, и вы можете реализовать ее в своих кодах, используя Javascript, css, et c

Частота

Вы не можете поглотить две анимации, если большая длительность не является фактором более короткой длительности.

Например, в ваших кодах мигание имеет длительность 1 с. Таким образом, ваше изображение длительность масштабирования , а также вся длительность должно быть выбором: 1 с, 2 с, 3 с, ... или 1/2 с, 1/3 с, ...
Для лучшего понимания приведу простой пример. Предположим, два изображения хотят быть анимированными.

<img src="1.png" id="img1">
<img src="1.png" style="margin-left: 50px;" id="img2">  

Рассмотрим две разные анимации для каждого

@keyframes k1
{
    25%
    {
        transform: rotate(-4deg);
    }
    50%
    {
        transform: rotate(0deg);
    }
    75%
    {
        transform: rotate(3deg);
    }
    100%
    {
        transform: rotate(0deg);
    }
}

@keyframes k2
{
    50%
    {
        transform: scale(1.2);
    }
    100%
    {
        transform: scale(1);
    }
}

Так как k2 проще, я сначала назначу его img2 с продолжительностью: 0,7 с

#img2
{
    animation: k2 0.7s linear infinite;
}

И на основании того, что было объяснено, я назначу анимацию k1 для img1 с продолжительностью 1,4 с. (НЕ 1.3s, НЕ 1.5s ОЧЕНЬ ВАЖНО! )

#img1
{
    animation: k1 1.4s linear infinite;
}

Если вы запустите этот код, вы увидите, что они потонули! Чтобы почувствовать концепцию лучше, измените длительность k1 ​​до 0,9 с. Теперь кажется, что они делают свое дело отдельно!
Примечание
Я установил для k1 значение 1,4 с (0,7 с × 2), потому что k1, по-видимому, представляет собой комбинацию одного go вперед и возвращается и использует 2x чувствует, что они танцуют вместе с одной и той же гармонией!

Фаза

В css фаза показана animation-delay. Изменение частоты (длительности) достаточно, чтобы поглотить две анимации, но если две анимации начнутся одновременно, будет лучше! Поэтому для иллюстрации установите задержку для img1 в 0,2 с. Они все еще тонут, но это не очень приятно! Теперь измените задержку на 0,7 с. Теперь это снова красиво! (Может быть, еще красивее)

enter image description here

Вернуться к вашему коду

Ваши изображения масштабируются с длительностью 1,2 с (40% от 3 с) ) и ваша продолжительность мигания текста равна 1 с, и, как вы можете видеть, они не имеют отношения друг к другу, поэтому вы не можете утонуть!

1 голос
/ 03 апреля 2020

Если вы управляете анимацией с тем же JavaScript l oop, что и сценарий пишущей машинки, она не потеряет syn c. Я переписал скрипт пишущей машинки, чтобы сделать это в приведенном ниже фрагменте кода.


startTypewriter() Объяснение

Сначала все собранные сообщения преобразуются в массив.

typewriter.getAttribute('data-typewriter').split(',');

Затем запускается анимация значка CSS. Поскольку JavaScript интервалы ждут своей продолжительности, прежде чем выполнить свой код, поэтому первое сообщение набирается путем вызова type() до создания интервала.

icon.classList.add('icon-animation');

type(typewriter, messages[0].trim(), animationDuration - pauseDuration);

Теперь интервал запускается, выполняется каждые 3 секунды по умолчанию. Первое, что происходит, это то, что анимация сбрасывается, если она как-то вышла из строя c.

icon.classList.remove('icon-animation');
window.setTimeout(function() {
  icon.classList.add('icon-animation');
}, 25);

Далее, сообщение набирается с помощью вызова type(). Прежде чем он заканчивается, выполняется проверка, чтобы увидеть, находится ли он в последнем элементе массива. Если это так, он начнется заново.

if (i == messages.length) i = 0;


type() Объяснение

В начале вычисляется значение timePerCharacter. Сообщение разбивается на массив, и вывод на пишущей машинке очищается

var timePerCharacter = duration / message.length;
var message = message.split('');
typewriter.innerHTML = '';

. Создается l oop, который запускается каждые timePerCharacter. Символ выводится на вывод пишущей машинки.

typewriter.innerHTML += message[i];

После того, как все символы выведены, l oop очищается

if (i == message.length) clearInterval(typeLoop);


Сниппент

var animationDuration = 3000;
var pauseDuration = 2000;

startTypewriter();

function startTypewriter() {
  var typewriter = document.getElementById('typewriter');
  var icon = document.getElementById('icon');
  var messages = typewriter.getAttribute('data-typewriter').split(',');
  
  icon.classList.add('icon-animation');
  
  type(typewriter, messages[0].trim(), animationDuration - pauseDuration);
    
  var i = 1;
  
  window.setInterval(function() {
    icon.classList.remove('icon-animation');
    window.setTimeout(function() {
      icon.classList.add('icon-animation');
    }, 25);
    
    type(typewriter, messages[i].trim(), animationDuration - pauseDuration);
    
    i++;
    
    if (i == messages.length) i = 0;
  }, animationDuration);
}

function type(typewriter, message, duration) {
  var timePerCharacter = duration / message.length;
  var message = message.split('');
  typewriter.innerHTML = '';

  var i = 0;

  var typeLoop = window.setInterval(function() {  
    typewriter.innerHTML += message[i];
    
    i++;
  
    if (i == message.length) clearInterval(typeLoop);
  }, timePerCharacter);
}
@keyframes icon {
  20% {
    transform: scale(0.9);
  }
  
  40% {
    transform: scale(1);
  }
  
  60% {
    transform: scale(0.9);
  }
  
  80% {
    transform: scale(1);
  }
  
  100% {
    transform: translateY(-200%);
  }
}

.icon {
  border-radius: 100%;
}

.icon-animation {
  animation: icon 3s;
}

@keyframes cursor {
  50% {
    color: transparent;
  }
}

.blinking-cursor {
  animation: cursor 1s steps(1) infinite;
}
<img id="icon" src="https://de7yjjf51n4cm.cloudfront.net/banners/amazonprime_newicon.jpg" class="icon">

<span id="typewriter" data-typewriter="
        Web Strategy,
    		UX Testing,
    		Content Management System,
    		Web Design,
    		Research and Analytics,
    		Information Architecture,
    		Strategic Consulting,
        Maintenance and Support
">
</span>
<span class="blinking-cursor">|</span>
1 голос
/ 31 марта 2020

Я думаю, что вы можете искать событие итерации анимации и событие запуска анимации .

Вместо того, чтобы просто использовать функцию myL oop для вызова сам, попробуйте использовать эти слушатели вместо этого.

Конец вашего js файла будет выглядеть следующим образом:

var i = 0;

function myLoop() {
  var dataType = document.getElementById("typewriter").dataset.typewriter,
    w = dataType.split(",");

  if (i < w.length -1 ) {
    typewriter(w[i]);
  }

  i++;
}

var imageElems = Array.from(document.querySelectorAll('.addsp_320x50_img'));
imageElems.forEach(elem=>{
 elem.addEventListener('animationstart',myLoop);
});

Где ".addsp_320x50_img" - это любой общий селектор, который вы даете всем изображениям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...