Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sync two animations using css keyframes?

I am working on solution

I have created a basic html banner where I want to keep image and text animations in sync.

Basically image animation is like scale logo for about 3 seconds, meanwhile logo is animated I want text for same in typing effect

I have created basic solution using css and javascript but it is not in sync

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>
like image 925
Janak Prajapati Avatar asked Mar 26 '20 10:03

Janak Prajapati


People also ask

Can you have multiple keyframes in CSS?

You can animate multiple properties inside a keyframe rule and use multiple keyframes to specify an element's property values at specific points in time.

Can you use keyframes with transition?

A keyframe can be a “step” If we set up a keyframe animation to change the background color of an element to change from orange to black (because orange is the new black, after all) on hover over five seconds, it will do exactly that. It will divide that change up over time and make the transition.

How does keyframe animation work CSS?

Each keyframe describes how the animated element should render at a given time during the animation sequence. Since the timing of the animation is defined in the CSS style that configures the animation, keyframes use a <percentage> to indicate the time during the animation sequence at which they take place.


1 Answers

Mathematically speaking, sinking means adjusting frequency and phase. I'll demonstrate each separately. Note that what I'm gonna explain is the concept and you can implement it in your codes using Javascript, css, etc

Frequency

You can't sink two animations unless the longer duration is a factor of shorter duration.

For example in your codes, blinking has a duration of 1s. So your image scaling duration and Also the whole duration must be a selection of either 1s, 2s, 3s, ... or 1/2s, 1/3s, ...
For better understanding let me make a simple example. Assume two images want to be animated.

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

Consider two different animations for each one

@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);
    }
}

So since k2 is simpler, I'll first assign it to img2 with duration of 0.7s

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

And based on what was explained, I will assign animation k1 to img1 with a duration of 1.4s. (NOT 1.3s NOT 1.5s VERY IMPORTANT!)

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

If you run this code you'll see they are sink! To feel the concept better, change the duration of k1 to 0.9s. Now it feels like they are doing their thing separately!
Note
I set k1 to 1.4s (0.7s × 2) because k1 seems to be a combination of one go forward and come back and using 2x feels they are dancing together with the same harmony!

Phase

In css, phase is showed by animation-delay. Modifying frequencies (duration) is enough to sink two animations but if two animation begin at the same time it will feel better! So to illustrate set a delay for img1 of 0.2s. They are still sink but it doesn't feel nice! Now change the delay to 0.7s. Now it's beautiful again! (Maybe even more beautiful)

enter image description here

Back to your code

Your images scale with duration of 1.2s (40% of 3s) and your text blinking duration is 1s and as you can see they are not factor of each other so you can't sink!

like image 92
Mohsen Nemati Avatar answered Sep 30 '22 15:09

Mohsen Nemati