Затримка анімації CSS при повторенні


81

Нещодавно я виявив, як "правильно" використовувати анімації CSS (раніше я відхилив їх, оскільки не мав змоги створювати складні послідовності, як це можна було робити в JavaScript). Тож зараз я дізнаюся про них.

Для цього я намагаюся зробити градієнтний "спалах", що проходить через елемент, подібний до індикатора прогресу. Подібно до впливу на рідні індикатори прогресу Windows Vista / 7.

@keyframes barshine {
  from {background-image:linear-gradient(120deg,rgba(255,255,255,0) -10%,rgba(255,255,255,0.25) -5%,rgba(255,255,255,0) 0%);}
  to {background-image:linear-gradient(120deg,rgba(255,255,255,0) 100%,rgba(255,255,255,0.25) 105%,rgba(255,255,255,0) 110%);}
}
.progbar {
  animation: barshine 1s 4s linear infinite;
}

Як бачите, я намагаюся затримати 4 секунди, а потім блиск, що проноситься через 1 секунду, повторюється.

Однак, здається, animation-delayєдине стосується першої ітерації, після якої блиск постійно повторюється.

Я "вирішив" це питання наступним чином:

@keyframes expbarshine {
  from {background-image:linear-gradient(120deg,rgba(255,255,255,0) -10%,rgba(255,255,255,0.25) -5%,rgba(255,255,255,0) 0%);}
  80% {background-image:linear-gradient(120deg,rgba(255,255,255,0) -10%,rgba(255,255,255,0.25) -5%,rgba(255,255,255,0) 0%);}
  to {background-image:linear-gradient(120deg,rgba(255,255,255,0) 100%,rgba(255,255,255,0.25) 105%,rgba(255,255,255,0) 110%);}
}
.progbar {
  animation: barshine 5s linear infinite;
}

fromі 80%абсолютно однакові, що призводить до "затримки" 80% тривалості анімації.

Це працює, але для моєї наступної анімації мені потрібно, щоб затримка була змінною (постійною для певного елемента, але змінною серед елементів, що використовують анімацію), тоді як сама анімація залишається точно такою ж довжиною.

З наведеним вище «рішенням» я б закінчив із повільнішою анімацією, коли все, що я хочу, - це більша затримка.

Чи можна animation-delayзастосувати заявку до всіх ітерацій, а не лише до першої?


На жаль, немає. animation-delay- це затримка перед початком анімації, і немає жодної подібної властивості. У JavaScript є поганий спосіб обходу, який ви, мабуть,
воліли

Відповіді:


55

Я мав подібну проблему і користувався

@-webkit-keyframes pan {
   0%, 10%       { -webkit-transform: translate3d( 0%, 0px, 0px); }
   90%, 100%     { -webkit-transform: translate3d(-50%, 0px, 0px); }
}

Трохи дратує, що вам доводиться підробляти свою тривалість, щоб врахувати "затримки" з обох кінців.


18

minitech має рацію в тому, що animation-delayвизначає затримку до початку анімації, а НЕ затримку між ітераціями. У редакторському проекті специфікації це добре описано, і було обговорення цієї функції, яку ви описуєте тут, що передбачає цю функцію затримки ітерації.

Незважаючи на те, що в JS може бути обхідне рішення, ви можете підробити цю затримку ітерації для спалаху індикатора прогресу, використовуючи лише CSS.

Оголосивши div flare position:absoluteі батьківський div overflow: hidden, встановивши стан 100% ключового кадру більше, ніж ширина індикатора виконання, і погравши з функцією синхронізації кубічного безіра та значеннями зсуву вліво, ви зможете емулювати ease-in-outабо linearсинхронізацію за допомогою "затримка".

Було б цікаво написати комбінацію менш / scss, щоб точно розрахувати лівий зсув та функцію синхронізації, щоб отримати цю точність, але я зараз не маю часу возитися з нею. Хотілося б побачити щось подібне, хоча!

Ось демонстрація, яку я зібрав разом, щоб показати це. (Я намагався наслідувати панель прогресу Windows 7 і трохи не встиг, але це демонструє, про що я говорю)

Демонстрація: http://codepen.io/timothyasp/full/HlzGu

<!-- HTML -->
<div class="bar">
   <div class="progress">
      <div class="flare"></div>
   </div>
</div>


/* CSS */

@keyframes progress {
  from {
    width: 0px;
  }
  to {
    width: 600px;
  }
}

@keyframes barshine {
  0% {
    left: -100px;
  }

  100% {
    left: 1000px;
  }
}
.flare {
  animation-name: barshine;
  animation-duration: 3s;
  animation-direction: normal;
  animation-fill-mode: forwards;
  animation-timing-function: cubic-bezier(.14, .75, .2, 1.01);
  animation-iteration-count: infinite;
  left: 0;
  top: 0;
  height: 40px;
  width: 100px;
  position: absolute;
  background: -moz-radial-gradient(center, ellipse cover,  rgba(255,255,255,0.69) 0%, rgba(255,255,255,0) 87%); /* FF3.6+ */
  background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(255,255,255,0.69)), color-stop(87%,rgba(255,255,255,0))); /* Chrome,Safari4+ */
  background: -webkit-radial-gradient(center, ellipse cover,  rgba(255,255,255,0.69) 0%,rgba(255,255,255,0) 87%); /* Chrome10+,Safari5.1+ */
  background: -o-radial-gradient(center, ellipse cover,  rgba(255,255,255,0.69) 0%,rgba(255,255,255,0) 87%); /* Opera 12+ */
  background: -ms-radial-gradient(center, ellipse cover,  rgba(255,255,255,0.69) 0%,rgba(255,255,255,0) 87%); /* IE10+ */
  background: radial-gradient(ellipse at center,  rgba(255,255,255,0.69) 0%,rgba(255,255,255,0) 87%); /* W3C */
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#b0ffffff', endColorstr='#00ffffff',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
  z-index: 10;
}
.progress {
  animation-name: progress;
  animation-duration: 10s;
  animation-delay: 1s;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  overflow: hidden;
  position:relative;
  z-index: 1;
  height: 100%;
  width: 100%;
  border-right: 1px solid #0f9116;
  background: #caf7ce; /* Old browsers */
  background: -moz-linear-gradient(top, #caf7ce 0%, #caf7ce 18%, #3fe81e 45%, #2ab22a 96%); /* FF3.6+ */
  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#caf7ce), color-stop(18%,#caf7ce), color-stop(45%,#3fe81e), color-stop(96%,#2ab22a)); /* Chrome,Safari4+ */
  background: -webkit-linear-gradient(top, #caf7ce 0%,#caf7ce 18%,#3fe81e 45%,#2ab22a 96%); /* Chrome10+,Safari5.1+ */
  background: -o-linear-gradient(top, #caf7ce 0%,#caf7ce 18%,#3fe81e 45%,#2ab22a 96%); /* Opera 11.10+ */
  background: -ms-linear-gradient(top, #caf7ce 0%,#caf7ce 18%,#3fe81e 45%,#2ab22a 96%); /* IE10+ */
  background: linear-gradient(to bottom, #caf7ce 0%,#caf7ce 18%,#3fe81e 45%,#2ab22a 96%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#caf7ce', endColorstr='#2ab22a',GradientType=0 ); /* IE6-9 */
}

.progress:after {
  content: "";
  width: 100%;
  height: 29px;
  right: 0;
  bottom: 0;
  position: absolute;
  z-index: 3;
  background: -moz-linear-gradient(left, rgba(202,247,206,0) 0%, rgba(42,178,42,1) 100%); /* FF3.6+ */
  background: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(202,247,206,0)), color-stop(100%,rgba(42,178,42,1))); /* Chrome,Safari4+ */
  background: -webkit-linear-gradient(left, rgba(202,247,206,0) 0%,rgba(42,178,42,1) 100%); /* Chrome10+,Safari5.1+ */
  background: -o-linear-gradient(left, rgba(202,247,206,0) 0%,rgba(42,178,42,1) 100%); /* Opera 11.10+ */
  background: -ms-linear-gradient(left, rgba(202,247,206,0) 0%,rgba(42,178,42,1) 100%); /* IE10+ */
  background: linear-gradient(to right, rgba(202,247,206,0) 0%,rgba(42,178,42,1) 100%); /* W3C */
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00caf7ce', endColorstr='#2ab22a',GradientType=1 ); /* IE6-9 */
}

.bar {
  margin-top: 30px;
  height: 40px;
  width: 600px;
  position: relative;
  border: 1px solid #777;
  border-radius: 3px;
}

46
Типовий CSS. Вони забезпечують CSS-анімацію, тому це не робиться в Javascript, і стилістика знаходиться в одному місці, але тоді, якщо ви хочете зробити щось більше, ніж просто основи, вам доведеться застосувати лабіринт хаків. Чому вони просто не впроваджують речі, які полегшують розробникам?
Джонатан.

10

Це те, що ви повинні робити. Це має працювати так, що у вас 1 секунда анімації, а потім 4 секунди затримки між ітераціями:

@keyframes barshine {
  0% {
  background-image:linear-gradient(120deg,rgba(255,255,255,0) 0%,rgba(255,255,255,0.25) -5%,rgba(255,255,255,0) 0%);
  }
  20% {
    background-image:linear-gradient(120deg,rgba(255,255,255,0) 10%,rgba(255,255,255,0.25) 105%,rgba(255,255,255,0) 110%);
  }
}
.progbar {
  animation: barshine 5s 0s linear infinite;
}

Тож я багато з цим возився, і ти можеш це робити, не будучи дуже невдалою. Це найпростіший спосіб укласти затримку між ітераціями анімації, яка становить 1. СУПЕР ЛЕГКО і 2. потрібно лише трохи логіки. Перегляньте цю танцювальну анімацію, яку я зробив:

.dance{
  animation-name: dance;
  -webkit-animation-name: dance;

  animation-iteration-count: infinite;
  -webkit-animation-iteration-count: infinite;
  animation-duration: 2.5s;
  -webkit-animation-duration: 2.5s;

  -webkit-animation-delay: 2.5s;
  animation-delay: 2.5s;
  animation-timing-function: ease-in;
  -webkit-animation-timing-function: ease-in;

}
@keyframes dance {
  0% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  25% {
    -webkit-transform: rotate(-120deg);
    -moz-transform: rotate(-120deg);
    -o-transform: rotate(-120deg);
    -ms-transform: rotate(-120deg);
    transform: rotate(-120deg);
  }
  50% {
    -webkit-transform: rotate(20deg);
    -moz-transform: rotate(20deg);
    -o-transform: rotate(20deg);
    -ms-transform: rotate(20deg);
    transform: rotate(20deg);
  }
  100% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
}

@-webkit-keyframes dance {
  0% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  20% {
    -webkit-transform: rotate(20deg);
    -moz-transform: rotate(20deg);
    -o-transform: rotate(20deg);
    -ms-transform: rotate(20deg);
    transform: rotate(20deg);
  }
  40% {
    -webkit-transform: rotate(-120deg);
    -moz-transform: rotate(-120deg);
    -o-transform: rotate(-120deg);
    -ms-transform: rotate(-120deg);
    transform: rotate(-120deg);
  }
  60% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  80% {
    -webkit-transform: rotate(-120deg);
    -moz-transform: rotate(-120deg);
    -o-transform: rotate(-120deg);
    -ms-transform: rotate(-120deg);
    transform: rotate(-120deg);
  }
  95% {
    -webkit-transform: rotate(20deg);
    -moz-transform: rotate(20deg);
    -o-transform: rotate(20deg);
    -ms-transform: rotate(20deg);
    transform: rotate(20deg);
  }
}

Я насправді прийшов сюди, намагаючись зрозуміти, як застосувати затримку в анімації, коли зрозумів, що ви просто 1. продовжуєте тривалість анімації та сорочки пропорцію часу для кожної анімації. Беоре, у мене вони тривали по 0,5 секунди загальною тривалістю 2,5 секунди. Тепер скажемо, що я хотів додати затримку, рівну загальній тривалості, тобто затримку 2,5 секунди.

Час анімації становить 2,5 секунди, а затримка 2,5, тому ви змінюєте тривалість на 5 секунд. Однак, оскільки ви подвоїли загальну тривалість, вам доведеться зменшити пропорцію анімації вдвічі. Перевірте фінал нижче. Для мене це чудово працювало.

@-webkit-keyframes dance {
  0% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  10% {
    -webkit-transform: rotate(20deg);
    -moz-transform: rotate(20deg);
    -o-transform: rotate(20deg);
    -ms-transform: rotate(20deg);
    transform: rotate(20deg);
  }
  20% {
    -webkit-transform: rotate(-120deg);
    -moz-transform: rotate(-120deg);
    -o-transform: rotate(-120deg);
    -ms-transform: rotate(-120deg);
    transform: rotate(-120deg);
  }
  30% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  40% {
    -webkit-transform: rotate(-120deg);
    -moz-transform: rotate(-120deg);
    -o-transform: rotate(-120deg);
    -ms-transform: rotate(-120deg);
    transform: rotate(-120deg);
  }
  50% {
    -webkit-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -o-transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    transform: rotate(0deg);
  }
}

В результаті:

Ось такі розрахунки, які ви, напевно, використовували б, щоб зрозуміти, як змінити тривалість анімації та% кожної частини.

бажана тривалість = x

бажана_тривалість = тривалість_анімації1 + тривалість_анімації2 + ... (і так далі)

бажаний_затримка = y

загальна тривалість = x + y

animation_part_duration1_actual = animation_part_duration1 * бажана тривалість / загальна_тривалість


французький плямистий :) (я теж французький, не хвилюйся)
Джулесбу

5

Я вважаю за краще написати трохи JavaScript, ніж зробити CSS менш керованим.

По-перше, застосовуйте анімацію CSS лише до зміни атрибута даних:

.progbar[data-animation="barshine"] {
    animation: barshine 1s linear;
}

Потім додайте javascript, щоб перемикати анімацію на половину затримки.

var progbar = document.querySelector('.progbar');
var on = false;

setInterval(function () {
    progbar.setAttribute('data-animation', (on) ? 'barshine' : '');
    on = !on;
}, 3000);

Або якщо ви не хочете, щоб анімація запускалася, коли вкладка прихована:

var progbar = document.querySelector('.progbar');
var on = false;

var update = function () {
    progbar.setAttribute('data-animation', (on) ? 'barshine' : '');
    on = !on;
    setTimer();
};

var setTimer = function () {
    setTimeout(function () {
        requestAnimationFrame(update);
    }, 3000);
};

setTimer();

2

Я зробив плакат на стіні, який рухається вліво і вправо з інтервалами. Для мене це працює:

.div-animation {
   -webkit-animation: bounce 2000ms ease-out;
    -moz-animation: bounce 2000ms ease-out;
    -o-animation: bounce 2000ms ease-out;
    animation: bounce 2000ms ease-out infinite;
    -webkit-animation-delay: 2s; /* Chrome, Safari, Opera */
    animation-delay: 2s;
    transform-origin: 55% 10%;    
}

@-webkit-keyframes bounce {
    0% {
        transform: rotate(0deg);
    }
    3% {
        transform: rotate(1deg);
    }
    6% {
        transform: rotate(2deg);
    }
    9% {
        transform: rotate(3deg);
    }
    12% {
        transform: rotate(2deg);
    }
    15% {
        transform: rotate(1deg);
    }
    18% {
        transform: rotate(0deg);
    }
    21% {
        transform: rotate(-1deg);
    }
    24% {
        transform: rotate(-2deg);
    }
    27% {
        transform: rotate(-3deg);
    }
    30% {
        transform: rotate(-2deg);
    }
    33% {
        transform: rotate(-1deg);
    }
    36% {
        transform: rotate(0deg);
    }
    100% {
        transform: rotate(0deg);
    }
}

2

Ще один спосіб досягти паузи між анімацією - застосувати другу анімацію, яка приховує елемент на потрібну суму затримки. Ця перевага дозволяє вам використовувати функцію пом'якшення CSS, як зазвичай.

.star {
  animation: shooting-star 1000ms ease-in-out infinite,
    delay-animation 2000ms linear infinite;
}

@keyframes shooting-star {
  0% {
    transform: translate(0, 0) rotate(45deg);
  }

  100% {
    transform: translate(300px, 300px) rotate(45deg);
  }
}

@keyframes delay-animation {
  0% {
    opacity: 1;
  }
  50% {
    opacity: 1;
  }
  50.01% {
    opacity: 0;
  }
  100% {
    opacity: 0;
  }
}

Це працює, лише якщо ви хочете, щоб затримка була кратною тривалості анімації. Я використав це, щоб злив падаючих зірок виглядав більш випадковим: https://codepen.io/ericdjohnson/pen/GRpOgVO


1

Ось невеликий фрагмент, який показує те саме саме протягом 75% часу, а потім він ковзає. Ця схема повторення добре емулює затримку:

@-webkit-keyframes slide    {
0%   {background-position: 0 0;}
25%  {background-position: 0 0;}
50%  {background-position: 0 0;}
75%  {background-position: 0 0;}
100% {background-position: 13em 0;}
}

@-moz-keyframes slide       {
0%   {background-position: 0 0;}
25%  {background-position: 0 0;}
50%  {background-position: 0 0;}
75%  {background-position: 0 0;}
100% {background-position: 13em 0;}
}

@keyframes slide            {
0%   {background-position: 0 0;}
25%  {background-position: 0 0;}
50%  {background-position: 0 0;}
75%  {background-position: 0 0;}
100% {background-position: 13em 0;}
}

0

Затримка можлива лише один раз на початку з нескінченною. затримка сортування не працює з нескінченним циклом. для цього вам потрібно зберегти приклад пробілів анімації ключових кадрів:

@-webkit-keyframes barshine {
  10% {background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#1e5799), color-stop(100%,#7db9e8));
    }
  60% {background: -webkit-linear-gradient(top, #7db9e8 0%,#d32a2d 100%);}
}

він буде оживляти від 10% до 60% і чекати завершення на 40% більше. Отже, 40% приходить із затримкою.

знайти скрипку приклад


0

Я знаю, що це старе, але я шукав відповідь у цьому дописі, і за допомогою jquery ви можете зробити це легко і без зайвих клопотів. Просто оголосіть свій ключовий кадр анімації в css і встановіть клас з атрибутами, які ви хотіли б. У моєму випадку я використовував анімацію tada з css animate:

.tada {
    -webkit-animation-name: tada;
    animation-name: tada;
    -webkit-animation-duration: 1.25s;
    animation-duration: 1.25s;
    -webkit-animation-fill-mode: both;
    animation-fill-mode: both;
}

Я хотів, щоб анімація запускалася кожні 10 секунд, тому jquery просто додає клас, через 6000 мс (достатньо часу для завершення анімації) він видаляє клас, а через 4 секунди додає клас знову, і тому анімація починається знову.

$(document).ready(function() {
  setInterval(function() {

    $(".bottom h2").addClass("tada");//adds the class

    setTimeout(function() {//waits 6 seconds to remove the class
      $(".bottom h2").removeClass("tada");
    }, 6000);

  }, 10000)//repeats the process every 10 seconds
});

Зовсім не складно, як один хлопець розмістив.


Я не впевнений, чому б ви використовували jQuery для .classList.add("tada"): D
Нієт Темний

Нагадую, це легше запам'ятати ... і вам зовсім не потрібно використовувати jquery, ви можете написати 3 рядки javascript, якщо хочете, а не лише 1 з jquery, це повністю залежить від людини, яка пише код :)
Маркос Silva Lepe

Не знаю, $(".bottom h2").addClass("tada")і я document.querySelector(".bottom h2").classList.add("tada")настільки схожий, що не варто витрат на завантаження / запуск коду jQuery: p
Niet the Dark

Думаю, ти маєш рацію щодо цього. Я побачив цей справді крутий слайдер у вільному фронт-енді, який використовує javascript, і оскільки я в основному використовую jquery, я намагався відтворити повзунок з ним, що і зробив, але це займає приблизно в 5 разів більше ресурсів оригінального слайдера, зробленого за допомогою javascript: що javascript набагато легший, ніж використання коду jquery, з іншого боку він менш багатослівний
Маркос Сільва Лепе

0

Ви можете створити "підроблену" затримку між нескінченними анімаціями суто за допомогою CSS. Це можна зробити розумно, визначивши точки анімації ключового кадру та швидкість тривалості анімації.

Наприклад, якщо ми хотіли анімувати підстрибуючий м’яч, і нам потрібна хороша затримка від 0,5 до 1 секунди між кожним відскоком, ми можемо зробити щось на зразок:

@keyframes bounce{
    0%{
        transform: translateY(0);
    }
    50%{
        transform: translateY(25%);
    }
    75%{
        transform: translateY(15%);
    }
    90%{
        transform: translateY(0%);
    }
    100%{
        transform: translateY(0);
    }
}

Ми робимо так, щоб переконатися, що куля повертається у вихідне положення набагато раніше ніж на 100%. У моєму прикладі я роблю це на 90%, що забезпечило мені затримку приблизно .1 с, що було досить добре для мене. Але, очевидно, для вашого випадку ви можете або додати більше ключових точок кадру, і змінити значення перетворення.

Крім того, ви можете додати додаткову тривалість анімації, щоб збалансувати ключові анімації кадру.

Наприклад:

 animation: bounce .5s ease-in-out infinite;

Скажімо, ми хотіли, щоб повна анімація закінчилася за .5 с, але ми хотіли додаткові .2 с затримки між анімаціями.

 animation: bounce .7s ease-in-out infinite;

Тож ми додамо додаткову затримку .2s, а в наших анімаціях ключових кадрів ми можемо додати більше процентних пунктів, щоб заповнити прогалини затримки .2s.


я зазвичай в кінцевому підсумку роблю це. недоліком є ​​те, що налаштувати анімацію стає дуже важко, оскільки кожна зміна часу вимагає зміни всіх значень. якщо ви не налаштуєте його належним чином із великою кількістю змінних sass, що зазвичай надто багато зусиль.
Беппе,

0

для прикордонного спалаху: насправді дуже просто: замініть від до до 99% чорним і, наприклад, 1% змістіть на синій, ви навіть можете зробити його коротшим, час анімації встановлено, наприклад, 5 с.

@keyframes myborder {
  0% {border-color: black;}
  99% {border-color:black;}
  100% {border-color: blue;}
 }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.