2
\$\begingroup\$

On Eric Amodio's website and JS.ORG, there is a Javascript animation which makes text appear/disappear as if it is being typed.

I tried to replicate something similar but far more basic on JSFiddle.

In my experiment, the words Code review appear typed, are hidden by toggle(200), and the words Code review appears again.

My final result was a mess of <span> tags and massive blocks of consequent setTimeout() JS functions.

<p><span id="bar"> |</span></p>
p {
  line-height: 10px;
}
setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>C</span>");
}, 100);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>o</span>");
}, 200);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>d</span>");
}, 300);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>e</span>");
}, 400);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'> </span>");
}, 500);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>R</span>");
}, 600);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>e</span>");
}, 700);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>v</span>");
}, 800);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>i</span>");
}, 900);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>e</span>");
}, 1000);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>w</span>");
}, 1100);

/* HIDE .TYPED-ANIMATION */

setTimeout(function() {
  $(".typed-letter").toggle(200);
}, 1300);

/* SECOND ITERATION */

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>C</span>");
}, 1600);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>o</span>");
}, 1700);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>d</span>");
}, 1800);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>e</span>");
}, 1900);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'> </span>");
}, 2000);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>R</span>");
}, 2100);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>e</span>");
}, 2200);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>v</span>");
}, 2300);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>i</span>");
}, 2400);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>e</span>");
}, 2500);

setTimeout(function() {
  $("#bar").before("<span class='typed-letter'>w</span>");
}, 2600);

Fiddle

  • How can I use functions, arrays and loops in my JS/jQuery instead of massive blocks of consequent setTimeout functions to simplify my code and make it more efficient?
  • How can I make it so that the text also disappears in a 'typed' way, instead of using toggle(200) to hide the text again?
\$\endgroup\$
0

1 Answer 1

3
\$\begingroup\$

For those who dont like typed.js, Modified code for the user code is.

Here,

  • content -> is the text that shows the typing effect.

  • speed -> is the typing effect speed. i -> this will help in iterating over the content till it reaches the content length.

  • timer -> we use this variable to assign the setTimeout(), so that after the text content is looped, we can use this variable to clear timer. This will prevent memory leakage.
  • intervalCount -> this variable is used to initialise how many times the content need to toggle.

const content = 'Code Review'; // text content to show typing effect
const speed = 1000; // this is the typing speed 
var i = 0;  // this is used to iterate over the text content
var timer = 0;  // this is used to set and clear timer. This will prevent memory leakage  
var intervalCount = 0; // this is used to set no. of times typing effect should loop.

Here initially i will be 0, then it checks with the content length. If i < content.length, then it will add content[i] to the dom. After that i is incremented by 1, then a setTimeout() function is called. This will invoke the typeSetting once again, at this time i will 1 and it will print content[1]. This will loop untill i become the content length.

This condition will iterate over the text content and displays them.

if (i < content.length) {
        el.before(`<span class='typed-letter'>${content[i]}</span>`);
        i++;
        timer = setTimeout(function() {
          typeSetting(intervalCount)
        }, speed);
      }

Now the else part, here first it will clear the timer ( Which will prevent the memory leakage ), then it decrement the intervalCount, check for the intervalCount is > 0, then set i = 0 ( this will help in printing the string from begining ). Again in a setTimeout() is called. At this time, the printed content is removed and starts printing again. Again the if loop explained above is executed. This will continue untill the intervalCount becomes 0.

else {
clearTimeout(timer);
intervalCount = intervalCount ? intervalCount - 1 : 0;
if (intervalCount) {
    i = 0;
    timer = setTimeout(function() {
    $(".typed-letter").empty();
    typeSetting(intervalCount);
    }, 300);
}
}      

For more realistic typing effect, we can add a blinking animation to the |.

.blinking{
    animation:blinkingText 1.2s infinite;
}
@keyframes blinkingText{
    0%{     color: #000;    }
    49%{    color: #000; }
    60%{    color: transparent; }
    99%{    color:transparent;  }
    100%{   color: #000;    }
}

const content = 'Code Review';
const speed = 100;
var i = 0;
var timer = 0;
var intervalCount = 0;

function typeSetting(interval) {
  let el = $('#bar');
  if (interval) intervalCount = interval;  
  if (i < content.length) {
    el.before(`<span class='typed-letter'>${content[i]}</span>`);
    i++;
    timer = setTimeout(function() {
      typeSetting(intervalCount)
    }, speed);
  } else {
    clearTimeout(timer);
    intervalCount = intervalCount ? intervalCount - 1 : 0;
    if (intervalCount) {
      i = 0;
      timer = setTimeout(function() {
        $(".typed-letter").empty();
        typeSetting(intervalCount);
      }, 300);
    }
  }
}

(function() {
  typeSetting(2); // may be you are using some kind of repetition count, set the count. If no params then will show 1 time.
})();
p {
  line-height: 10px;
}
.blinking{
    animation:blinkingText 1.2s infinite;
}
@keyframes blinkingText{
    0%{     color: #000;    }
    49%{    color: #000; }
    60%{    color: transparent; }
    99%{    color:transparent;  }
    100%{   color: #000;    }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<p><span id="bar" class="blinking"> |</span></p>

Here no external packages are used, no libraries. Its pure javascript.

\$\endgroup\$
4
  • \$\begingroup\$ it's kind of sad that you don't mention the superiority of looping over copy-pasting code, which is the core improvement of your code over the code presented in the question. Instead you write as if you just reimplemented this code from scratch, which would make this a bad answer (because it doesn't explain why it's better than the original code) \$\endgroup\$
    – Vogel612
    Commented Feb 5, 2020 at 10:28
  • \$\begingroup\$ @Vogel612 Just replaced his setTimeOut() dump to single setTimeOut(), thats all. Its a kind of refactoring the original code. I thought I have added enough comments. Do we need to add comment for each block ??. Can you share a sample of commenting :) \$\endgroup\$ Commented Feb 5, 2020 at 10:44
  • \$\begingroup\$ You'll want to explain why you looped. I see that you explain what the code does, but the interesting part during a review is the why :) \$\endgroup\$
    – Vogel612
    Commented Feb 5, 2020 at 10:51
  • \$\begingroup\$ @Vogel612 got that. I will add a detailed explanation. :) . I am just a starter here. Thanks for the feedback. \$\endgroup\$ Commented Feb 5, 2020 at 10:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.