I have coded this small script which increments a given value, in this case 200, by 1 every 3.2 seconds.
var i = 200;
function increment() {
i++;
document.getElementById('generated').innerHTML = Number(i).toLocaleString('en');
}
setInterval('increment()', 3200);
I'm trying to make the script stop increasing the value once it reaches a certain point (let's say 300 for example). I'm sure it's a simple fix but I can't think up of how to go about this.
You need to save the interval and then clear it:
var i = 200;
function increment() {
if (i >= 300) {
clearInterval(interval);
return;
}
i++;
document.getElementById('generated').innerHTML = Number(i).toLocaleString('en');
}
var interval = setInterval(increment, 3200);
Note that you can pass a function name instead of using the "interval()" string notation.
Here is a fiddle (I've sped up the time so that it doens't take forever to prove a point)
Hope it helps!
var i = 200;
function increment() {
if (i == 300) {
// stop when it hits 300
window.clearInterval(id);
return;
}
i++;
document.getElementById('generated').innerHTML = Number(i).toLocaleString('en');
}
var id = window.setInterval('increment()', 3200);
I think you could put it in IF statement as:
var i = 200;
function increment() {
if(i<300){
i++
}
}
increment();
You could use a for loop.
var i = 200;
var max = 300;
function increment() {
for (i < max; i++) {
document.getElementById('generated').innerHTML = Number(i).toLocaleString('en');
}
}
setInterval('increment()', 3200);
More info here: http://www.w3schools.com/js/js_loop_for.asp
Related
I'm creating a small game in javascript and I'm using svg for the graphics. Right now I'm having a problem with updating the game in the middle of a game tick. If I exit my loop directly after I update the fill attribute with "setAttributeNS", it's redrawn, but if I don't do that, it isn't updated until after "game_tick" is over. Even worse, if I call "game_tick" multiple times in a row, the svg objects aren't updated until after I've run all of the "game_tick"s instead of being updated after each one.
function game_tick(){
num_grid_copy = num_grid.slice();
for (var x = 0; x < num_squares_x; x += 1) {
for (var y = 0; y < num_squares_x; y += 1) {
var n = get_neighbors(x,y);
var isAliveInNextGen = next_gen(n, num_grid[x*num_squares_x+y]);
num_grid_copy[x*num_squares_x+y] = isAliveInNextGen;
if (isAliveInNextGen == 1){
rect_grid[x*num_squares_x+y].setAttributeNS(null, 'fill', '#0099ff');
}
else {
rect_grid[x*num_squares_x+y].setAttributeNS(null, 'fill', '#fff');
}
}
}
num_grid = num_grid_copy;
}
Thanks to valuable input from Robert I realized that javascript execution and page rendering are done in the same thread. I changed the function to the following:
function start() {
var inc = 0,
max = 25;
delay = 100; // 100 milliseconds
var repeat = setInterval(function() {
game_tick();
if (++inc >= max)
clearInterval(repeat);
},
delay);
}
This works fine. I can set the delay and the number of times it repeats.
The behaviour I want is this: The background color changes to say, gold, and remains that color for say X length of time. Then, background color changes to say, red, and remains that color for say Y length of time. The background color then changes back to gold and remains that color for X length of time. Then the background color changes back to red and stays that way for Y length of time. This whole kit and caboodle executes in a loop-style fashion for Z number of times and then ends.
I've tried putting setInterval'd functions into a for loop (in order to count the number of times we make the change) but have found that all of the functions that have been set to setInterval themselves all start running the interval timers at the same time (not in sequence).
I hope this is clear. Here is a JSFiddle of my efforts: http://jsfiddle.net/6WE6s/3/ I've managed to get the background color to change in a even pattern, but I want the pattern described above and I'm confused as to what to do next.
Thanks in advance for the help! :)
var colors = [
['gold', 2000], // X = 2000 miliseconds
['red', 1000] // Y = 1000
],
repeat = 3, // Z = 3,
index = 0, // current position in colors array
changeColor = function( ) {
// if index == colors.length then mod = 0
var mod = index % colors.length;
if(!index || mod || --repeat ) {
index = mod;
var data = colors[ index++ ]; // data = [ currentColor, currentColorTimeout ]
document.body.style.background = data[0];
setTimeout( changeColor, data[1] ); // and so on
}
//if index >0 && index == last
//then decrement `repeat` and check if is == 0
//nothing to do :)
};
changeColor(); // run
This is a simple example. You can make function with arguments(colors,repeats) and its body as above.
Note:
setInterval isn't suitable for this purpose because in setInterval you pass timeout once
If repeat initially is 0 will be an infinite number of repetitions
Don't use setInterval(). With setTimeout() you can do something like this:
function changeColors(colors, repeats) {
var i = 0;
if (typeof repeats === "undefined")
repeats = 1;
function doNext() {
if (i >= colors.length){
if (--repeats > 0)
i = 0;
else
return;
}
$('body').css('background-color', colors[i].color);
setTimeout(doNext, colors[i++].delay);
}
doNext();
}
changeColors([{color : "gold", delay : 2000},
{color : "red", delay : 4000}],
3);
You can add as many colours as you like, each with their own delay, by adding more elements to the array you pass to changeColors(). The function will go through the colours in turn, and do the whole sequence the number of times specified in the repeats parameter.
Demo: http://jsfiddle.net/nnnnnn/6WE6s/10/
Here's my effort - no jQuery required:
function colorCycle(el, count, cols) {
var i = 0,
n = cols.length;
// allow this to work on any element given its ID
el = (typeof el === "string") ? document.getElementById(el) : el;
if (n === 0) {
return; // no colours?
} else if (n === 1) {
count = 1; // don't trigger any timers if there's only one colour
}
// all of the hard work is done here
(function repeat() {
var interval = cols[i][1];
el.style.backgroundColor = cols[i][0];
// only do the whole cycle "count" times - 0 = forever
if (++i === n) {
if (count && !--count) {
return;
}
i = 0;
}
setTimeout(repeat, interval); // call myself
})(); // IIFE starts the cycle straight away
};
colorCycle(document.body, 5, [
['red', 1000],
['gold', 500]]);
See http://jsfiddle.net/alnitak/42PeT/
Abstain from using setInterval. Reference here.
EDIT: I've missed the different delay in calls.
var colors = ["#FF0000", "#00FF00", "#0000FF"];
var times = [1000, 2000, 3000];
var backgroundColor = "";
var counter = 0;
var changeBackground = function () {
// if we ran out of colors — do nothing: this simply goes out
// of the function, without continually calling setTimeout.
if (counter >= colors.length)
return;
// you fetch your new color here and increase the counter
// The counter keeps count of how many animations you've done.
backgroundColor = colors[counter];
// increase the counter to point to the next index of colors
// array you'll use in a subsequent call
counter++;
// do your magic voodoo change background animation here.
// I'm just doing a console.log() to be sure this works.
// Your question was framework agnostic, the answer should be too.
console.log(backgroundColor);
// setInterval to repeat
window.setTimeout(changeBackground, times[counter]);
}
window.setTimeout(changeBackground, times[counter]);
try this
var colors = [];
colors.push({color:"gold", time:4000}); //4000 X length of time
colors.push({color:"red", time:2000}); //2000 Y length of time
var numberofTimes = 50; //50 Z number of times
var $body;
var times = 0; // counter for tracking
var currentColor = {}; //currentColor info can be used to get the current
$(function(){
$body = $('body');
changeBG();
});
function changeBG()
{
currentColor = colors[times % colors.length];
$body.css('background-color',currentColor.color);
times++;
if(times<numberofTimes)
setTimeout(changeBG, currentColor.time);
}
check this quick DEMO
A basic example iterating an array of color and time arrays with setTimeout.
(function() {
var i = 0,
colorsTimes = [['gold', 'red', 'gold', 'red', 'gold'],
[2000, 4000, 2000, 4000, 2000]];
function switchColors() {
setTimeout(function() {
$('body').css('background-color', colorsTimes[0][i]);
if (++i < colorsTimes[0].length) switchColors();
}, colorsTimes[1][i]);
}
switchColors();
}());
Fiddle
Using setTimeout:
var doCount = (function() {
var count = 0;
var interval;
var limit = 5; // default
return function(num) {
limit = num || limit;
if (count < limit) {
count++;
console.log('running number ' + count);
interval = setTimeout(arguments.callee, 1000);
} else {
interval && clearTimeout(interval);
}
}
}())
Using setInterval:
var doCount = (function() {
var count = 0;
var interval;
var limit = 5; // default
return function(num) {
limit = num || limit;
if (interval) {
if (++count >= limit) {
interval && clearInterval(interval);
}
console.log('running number ' + count);
} else {
interval = setInterval(arguments.callee, 1000);
}
}
}())
The advantage of setTimeout is that you can adjust the time between runs to make it more regular, setInterval just tries to run as regularly as it can.
I'm currently trying to wrap my head around some JavaScript.
What I want is a text to be printed on the screen followed by a count to a given number, like so:
"Test"
[1 sec. pause]
"1"
[1 sec. pause]
"2"
[1 sec. pause]
"3"
This is my JS:
$(document).ready(function() {
var initMessage = "Test";
var numberCount = 4;
function count(){
writeNumber = $("#target");
setTimeout(function(){
writeNumber.html(initMessage);
},1000);
for (var i=1; i < numberCount; i++) {
setTimeout(function(){
writeNumber.html(i.toString());
},1000+1000*i)};
};
count();
});
This is my markup:
<span id="target"></span>
When I render the page, all I get is "Test" followed by "4".
I'm no JavaScript genius, so the solution could be fairly easy. Any hints on what is wrong is highly appreciated.
You can play around with my example here: http://jsfiddle.net/JSe3H/1/
You have a variable scope problem. The counter (i) inside the loop is only scoped to the count function. By the time the loop has finished executing, is value is 4. This affects every setTimeout function, which is why you only ever see "4".
I would rewrite it like this:
function createTimer(number, writeNumber) {
setTimeout(function() {
writeNumber.html(number.toString());
}, 1000 + 1000 * number)
}
function count(initMessage, numberCount) {
var writeNumber = $("#target");
setTimeout(function() {
writeNumber.html(initMessage);
}, 1000);
for (var i = 1; i < numberCount; i++) {
createTimer(i, writeNumber);
}
}
$(document).ready(function() {
var initMessage = "Test";
var numberCount = 4;
count(initMessage, numberCount);
});
The createTimer function ensures that the variable inside the loop is "captured" with the new scope that createTimer provides.
Updated Example: http://jsfiddle.net/3wZEG/
Also check out these related questions:
What's going on under the hood here? Javascript timer within a loop
JavaScript closure inside loops – simple practical example
In your example, you're saying "2, 3, 4 and 5 seconds from now, respectively, write the value of i". Your for-loop will have passed all iterations, and set the value of i to 4, long before the first two seconds have passed.
You need to create a closure in which the value of what you're trying to write is preserved. Something like this:
for(var i = 1; i < numberCount; i++) {
setTimeout((function(x) {
return function() {
writeNumber.html(x.toString());
}
})(i),1000+1000*i)};
}
Another method entirely would be something like this:
var i = 0;
var numberCount = 4;
// repeat this every 1000 ms
var counter = window.setInterval(function() {
writeNumber.html( (++i).toString() );
// when i = 4, stop repeating
if(i == numberCount)
window.clearInterval(counter);
}, 1000);
Hope this helps:
var c=0;
var t;
var timer_is_on=0;
function timedCount()
{
document.getElementById('target').value=c;
c=c+1;
t=setTimeout("timedCount()",1000);
}
function doTimer()
{
if (!timer_is_on)
{
timer_is_on=1;
timedCount();
}
}
What is the best way to count from one preset number to a higher or lower number on input, and show the animation of the change?
There will be an initial amount, let say 100; and when we give it an increased or decreased number, let's say 200, the original 100 will count up animated to 200.
You can use setInterval like this:
var count = 100;
var number = 110;
var interval = setInterval(function(){
document.getElementById('elementID').innerHTML = ++count;
if (count === number) { clearInterval(interval) }
}, 500);
Use ++count if you want to increase or --count if you want to decrease.
Working Example
Not 100% sure I understand what you mean, but the count thing is simple:
function count() {
var i; //declare i for use later in the function
for (i = 100; i <= 200; i++) {
alert(i);
}
}
I have three yellow bars and each of them needs to come from left to right. For that, I have produced this code, but it only works on the last one. Can anyone correct this code; I need to work with pure JavaScript. I am not using any framework. Thanks.
window.onload = function(){
var yellowTitles = document.getElementById('magazine-brief').getElementsByTagName('h2');
for(i=0; i< yellowTitles.length; i++) {
var header = yellowTitles[i];
var timer = i*500;
var yellowBar = setTimeout(animeYellowBar,timer);
function animeYellowBar(){
header.style.left= "0";
}
}
}
Here's how I'd solve the problem:
var yellows = document.getElementById('magazine-brief').getElementsByTagName('h2');
// this will force the header number to be bound correctly
// also animates the div across the page by tracking the current position of x
function createMotion(num){
var currPos = 0;//current x position
var delta = 10;//move by this amount
setInterval(function(){
currPos += delta
yellows[num].style.left = currPos;
}, num * 500);
}
for (var i = 1; i < yellows.length; i++)
{
createMotion(i);
}
Note the function "createMotion" - added so the number "i" is correctly reference in the setInterval function.
Shouldn't you be incrementing your CSS left value instead of just setting it to 0? Why have a timeout at all if you're just going to set the value without gradually incrementing or decrementing?
If you do actually want to use a gradual animation, look at this tutorial : http://www.schillmania.com/content/projects/javascript-animation-1/
Very descriptive and possibly what you want.
By the time your timeout function runs, header refers to your last h2.
Try editing your timeout function to this:
function animeYellowBar(){
var thisheader=header;
thisheader.style.left= "0";
}
var yellows = document.getElementById('magazine-brief').getElementsByTagName('h2');
for (var i = 0; i < yellows.length; i++)
{
(function(idx, el){
window.setTimeout(function(){
var interval = window.setInterval(function(){
el.style.left = parseInt(el.style.left) + 10; // adjust this movement step
if (parseInt(el.style.left) >= 0)
{
el.style.left = 0;
window.clearInterval(interval);
}
}, 100); // adjust this number for animation speed
}, (idx++) * 500);
})(i, yellows[i]);
}