Reputation: 49
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
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
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