Reputation: 96544
I want to slowly rotate the letters in a string using 2 second pauses.
I'm trying to use setTimeout(function, delay)
but it doesn't pause it runs the entire script in under a second. How can I do this?
My code is at https://jsfiddle.net/6un4xhuj/
<html>
<head>
<link type="text/css" href="style.css">
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<h1>JS</h1>
<h2 id='for'>For: String Rotations</h2>
<h3 id='result'>Result:</h3>
<h4></h4>
<span id="end_of_results"></span>
<script src="main.js"></script>
</body>
</html>
js:
'use strict';
function display(string) {
$("span#end_of_results").before( $( "<h4>" + string + "</h4>" ) );
}
var string="rotate me";
for (var i = 0; i <= string.length; i++) {
setTimeout(display(string), 2000);
string=string[0,string.length - 1] + string.slice(0,-1);
}
I get this output but all of it immediately, not step by step.
Upvotes: 1
Views: 1467
Reputation: 963
You are beginning the 2 second wait immediately for all instances of setTimeout. The simplest way to fix your code is to increase the wait each time you go through your loop:
change this:
setTimeout(display(string), 2000);
to this:
setTimeout(display(string), (i+1)*2000);
Alternatively you could make a single HTML element update on a 2 second interval using setInterval()
like this:
<div class="rotating-text"> rotate me</div>
<script>
setInterval(function(){
$('.rotating-text').each(function(){
var string = $(this).text();
string = string[0,string.length - 1] + string.slice(0,-1);
$(this).text(string);
});
}, 2000);
</script>
This example applies to everything with a class rotating-text
http://codepen.io/t3hpwninat0r/pen/eZVYqw
Upvotes: 1
Reputation: 96544
I've accepted andy's answer, also based on it, I create this version to only scroll once:
<h1>JS</h1>
<h2 id='for'>For: String Rotation</h2>
<h2 id='result'>Result:</h2>
'use strict';
function rotate(string) {
string = string[0, string.length - 1] + string.slice(0,-1);
$("h2#result").html( $( "<h3>" + string + "</h3>" ) ).animate(100);
rotations+=1
if (rotations > string.length) {
return;
}
setTimeout(rotate, 50, string);
}
var string="rotate this string ";
var rotations=0
rotate(string);
fiddle at https://jsfiddle.net/xb865yw6/3/
Upvotes: 1
Reputation: 1
You can use .queue()
, .delay()
"use strict";
var elem = $("h2#result");
var string = "rotate this string";
elem.append("<br>" + string)
.queue("_fx", $.map(Array(string.length), function(value) {
return function(next) {
string = string[0,string.length - 1] + string.slice(0,-1);
$(this).delay(2000).queue(function() {
$(this).append("<br>" + string).dequeue();
next()
})
}
})).dequeue("_fx")
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<h1>JS</h1>
<h2 id='for'>For: String Rotation</h2>
<h2 id='result'>Result:</h2>
Upvotes: 0
Reputation: 63550
Get rid of the loop and just recurse the same function passing in the string each time. This code repeats without end so you might want to add a condition as per your requirements.
function thing(string) {
string = string[0, string.length - 1] + string.slice(0,-1);
$("h2#result").html( $( "<h3>" + string + "</h3>" ) );
setTimeout(thing, 2000, string);
}
thing(string);
Upvotes: 5
Reputation: 1083
setTimeout is async, which means the for loop is completing immediately. Also... you are calling display directly instead of passing the function reference. The same algorithm using callbacks would be like this:
jsfiddle: https://jsfiddle.net/w1x0csp9/
'use strict';
var i = 0;
var string="rotate me";
function display() {
if(i > string.length) {
return;
}
$("span#end_of_results").before( $( "<h4>" + string + "</h4>" ) );
string = string[0,string.length - 1] + string.slice(0,-1);
i++;
setTimeout(display, 2000);
}
display();
Upvotes: 1
Reputation: 7599
setTimeout
takes a function in your argument. In your code setTimeout(display(string), 2000);
, you pass the result of invoking the function display(string)
into setTimeout. To make this more evident, assign it to a variable like this:
var result = display(string); // undefined
setTimeout(result, 2000); // Not right
You'll need to use something like bind
, or just create a function that returns a function:
setTimeout(function () {
// Modify your string here
string=string[0,string.length - 1] + string.slice(0,-1);
display(string)
}, 2000);
Upvotes: 2