buzz eclair
buzz eclair

Reputation: 49

Generate multiple random letters to create a decryption effect?

I want create an effect like this a link!. (The name of the planet in the background)

So i need to generate many random letter before to display letter of my word one by one.

In my test, i try to display the word moon in my div.planet-name, letter by letter with a delay of 1000ms. And Before display a letter of Moon i want generate many random letter.

But when i use the function randomLetterEffect i stay blocked on the first letter and the word moon doesn't appear !

why i don't generate random letter in text.substring(0, 1), text.substring(0, 2), text.substring(0, 3), etc ... but only in text.substring(0, 0) ?

i try this :

var text = $('.planet-menu').data('planet');
var letterChoice = "abcdefghijklmnopqrstuvwxyz"
var length = text.length;
var timeOut;
var timeOut2;
var character = 0;


(function typeWriter() { 
    timeOut = setTimeout(function() {
        character++;
        
        var type = text.substring(0, character);

        (function ramdomLetterEffect(){
            timeOut2 = setTimeout(function() {

                var type = text.substring(0, character);
                var randomLetter = letterChoice.charAt(Math.floor(Math.random() * letterChoice.length));
                $('.planet-name').text(randomLetter);
                ramdomLetterEffect();

                if (character == length) {
                    clearTimeout(timeOut2);
                }

            },200);
        }());

        $('.planet-name').text(type);
        typeWriter();
        
        if (character == length) {
            clearTimeout(timeOut);
        }
        
    }, 1000);
}());
<div class="planet-menu" data-planet="moon"></div>

<div class="planet-name"></div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

I am most grateful for your read !

Upvotes: 1

Views: 470

Answers (2)

Patrick Roberts
Patrick Roberts

Reputation: 51886

I decided to write a very modular approach to generating this particular effect, that separates the effect itself from how it is rendered:

const text = $('.planet-menu').data('planet')
const letterChoice = 'abcdefghijklmnopqrstuvwxyz'

obfuscate({
  // required: input to obfuscate
  string: text,
  // 1s for each character
  // default is 1s
  duration: text.length,
  // 200ms for each frame
  // default is 60 fps
  fps: 5,
  // only lowercase letters
  // default is all printable ascii characters
  random: letterChoice,
  // consume characters in sequential order
  // default is random order
  next ([index]) { return index },
  // required: updates view
  render (string) { $('.planet-name').text(string) }
}).then(() => {
  // when effect is completed
  console.log('done!')
})
.planet-name {
  font-family: monospace;
}
<div class="planet-menu" data-planet="moon"></div>
<div class="planet-name"></div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/patrickroberts/9fe4606118237749749c7bffe95fc066/raw/8f04a89d79be0659f29a8900982db50794386ed9/obfuscate.js"></script>

However, I find that increasing the frame-rate of the randomly generated characters tends to make the effect look more aesthetically pleasing:

const text = $('.planet-menu').data('planet')
const letterChoice = 'abcdefghijklmnopqrstuvwxyz'

obfuscate({
  // required: input to obfuscate
  string: text,
  // 1s for each character
  // default is 1s
  duration: text.length,
  // only lowercase letters
  // default is all printable ascii characters
  random: letterChoice,
  // consume characters in sequential order
  // default is random order
  next ([index]) { return index },
  // required: updates view
  render (string) { $('.planet-name').text(string) }
}).then(() => {
  // when effect is completed
  console.log('done!')
})
.planet-name {
  font-family: monospace;
}
<div class="planet-menu" data-planet="moon"></div>
<div class="planet-name"></div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/patrickroberts/9fe4606118237749749c7bffe95fc066/raw/8f04a89d79be0659f29a8900982db50794386ed9/obfuscate.js"></script>

Upvotes: 0

Saeed
Saeed

Reputation: 5488

If I correctly understand your problem, These issues are in your code:

1-Check length of string before updating the text of class

if (character==length) {
  clearTimeout(timeOut2);
  return;
}

2-Update the text of class like this

$(".planet-name").text($(".planet-name").text().substr(0, character) + randomLetter);

Working code

var text = $(".planet-menu").data("planet");
var letterChoice = "abcdefghijklmnopqrstuvwxyz";
var length = text.length;
var timeOut;
var timeOut2;
var character = 0;

(function typeWriter() {
  timeOut = setTimeout(function() {
    character++;

    var type = text.substring(0, character);

    (function ramdomLetterEffect() {
      timeOut2 = setTimeout(function() {
        var type = text.substring(0, character);
        var randomLetter = letterChoice.charAt(
          Math.floor(Math.random() * letterChoice.length)
        );
        if (character == length) {
          clearTimeout(timeOut2);
          return;
        }
        $(".planet-name").text($(".planet-name").text().substr(0, character) + randomLetter);


        if (character == length) {
          clearTimeout(timeOut2);
        } else {
          ramdomLetterEffect();
        }
      }, 200);
    })();

    $(".planet-name").text(type);
    typeWriter();

    if (character == length) {
      clearTimeout(timeOut);
    }
  }, 1000);
})();
<div class="planet-menu" data-planet="moon">
</div>

<div class="planet-name"></div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Upvotes: 2

Related Questions