Javascript, object with set lifetime? - javascript

I have run in to a problem I do not know how to code in JavaScript really. The thing is I would like to be able to create a lot of objects added to an Array. when objects are created to be added to this array they will have a "lifetime". When this lifetime runs out this object should be removed from the array.
What Im trying to build here is a particle system where particles will vanish from being rendered after the particles lifetime in question have expired.
Anyone who have a good idea or example for this?
I have thought about using setTimeout, setInterval and clearInterval but not sure how this would be most effective.

Something like this?
Update for Felix Kling:
var a = [], next = function() {
a = a.slice(0,-1);
document.body.innerHTML += a.length + "<br />";
if (a.length != 0)
setTimeout(next, 100);
};
for (var i = 0; i < 100; i++) {
a.push({hi: 1});
}
setTimeout(next, 100);​

You can use the code sample of micha. On every call of "next" function you can update the state of you particles (position, velocity, etc). Also you can track the time of the creation of the particles and on every "next" call check if the current time minus the creation time exceeds certain constant and if it does then remove the particles. Depending on the required quality of the animation you may want to reduce the time between timeouts, e.g. setTimeout(next, 25);
Good luck :)

Related

How to get smooth counter animations

I should display an animated counter. Ideally, there should be an continous animation of the number change. The situation looks like the following:
I get every minute a new value.
The counter should show the real value (no fake).
There are times where there is no value change.
Sometimes there counter should spin faster and sometimes slower (depending on the value change).
My idea was to use the last two values and animate between them. Depending on the difference the speed has to change. But I didn't find a counter which allows to change the speed afterwards. Or do you have another idea?
How are all the other websites with a counter doing it? Do they fake?
Edit:
I tried different counter - currently I'm using jOdometer. My current code base is:
var counter = $('.counter').jOdometer({
counterStart: '0',
numbersImage: '/img/jodometer-numbers-24pt.png',
widthNumber: 32,
heightNumber: 54,
spaceNumbers: 0,
offsetRight:-10,
speed:10000,
delayTime: 300,
maxDigits: 10,
});
function update_odometer() {
var jqxhr = $.getJSON("/number.php?jsonp=?")
.done(function(data){
console.log(data);
total = data['Total'];
counter.goToNumber(total);
})
.fail(function(data){
console.log(data);
});
};
update_odometer();
setInterval(update_odometer, 60000);
The counter currently counts from zero to my number, but I want to change this behavior (counting from the next-to-last to the last value - but I have problems with my AJAX call [see here]). It is also possible that I change the library if needed. I looked into jquery.jodometer.js and perhaps I get it working to create a function which changes the speed on the fly.
But the reason why I didn't attached the code was that I search for the programming procedure behind the code. Is it possible to get such a live counter? How does the procedure does look like?
Solution:
Setting the speed solves the problem because the library does the animation for me:
speed:60000
You only have to match the speed of the animation with the update interval.
A simple for loop from current value to value to be updated should solve your problem.
Inside your done function,
for(var i=current_odo_value; i<=data['Total']; i++) {
counter.goToNumber(i);
}
If you can control the speed in your library, this ought to do it. Since the speed is directly proportional to the difference between current value and updated value, that difference can be sent to plugin as the required speed value.
I'm assuming only increase in fetched total value. If it can decrease as well, you need to handle that condition as well.

variable doesn't update when function restarts (javascript)

I'm going to try my best to ask this question without a huge wall of code. Basically I have written a very simple math quiz game. In this game you select a difficulty, the number of questions you want, and the game starts. It asks that number of questions and then you get a score and then the game is over. However, you can restart the game. When you restart, it simply returns you to the home screen, then you can select your options again. The only problem is, we need to keep track of the number of questions remaining in the quiz, the first time around, it works well. We pass numQuestions to the game function. The second time, however, even if I pass numQuestions=10, the value remains 0 from the first time I played the game. Here is the game function:
function startGame(difficulty,numQuestions,score){
// begins game, excluded that come its just some acsii art
// asks question
var q = new question(difficulty);
$("#gameInside").html(q.string);
$("#gameInside").data('answer',q.answer);
// gives answer options
for (var ii=0;ii<=3;ii++){
$("#answers").append("<button class='answerButton'>"+q.answerArray[ii]+"</button>")
}
// starts timer
var b = document.getElementById("timer");
timer = new stopWatch(b, {delay: 100});
timer.start();
},5500)
// when answer is clicked, go here
$("#gameScreen").on("click",".answerButton",function() {
// this seems to be the problem: on the second time I play the game, numQuestions remains the value from the first game and continues to go down (-1,-2) and since my selector is (>0), the else statement fires.
numQuestions--;
var time = parseFloat($("#timer span").html());
var correct = parseFloat($("#gameInside").data('answer'));
var userAnswer = parseFloat($(this).html());
if (correct==userAnswer)
tempScore = Math.round(calculateScore(time)*100)/100;
else
tempScore = 0;
score += tempScore;
$("#score").html(Math.round(score*100)/100);
if (numQuestions > 0) {
var q = new question(difficulty);
$("#gameInside").html(q.string);
$("#gameInside").data('answer',q.answer);
$("#answers").empty();
for (var ii=0;ii<=3;ii++){
$("#answers").append("<button class='answerButton'>"+q.answerArray[ii]+"</button>")
}
timer.reset();
} else {
$("#answers").empty();
$("#gameInside").html('Game Over! Thanks for Playing!');
timer.stop();
}
});
}
any ideas? Thanks
edit:
$(".numberQButton").click(function(){
numQuestions = parseFloat($(this).html());
$("#numQuestionsScreen").hide();
$("#gameScreen").show();
$("#score").html(0);
startGame(difficulty,numQuestions,score);
});
You're problem (I think) lies in closures. When you declare a function in javascript, any accessing of a variable from outside it's own scope generates what is called a closure. In this case, numQuestions is accessed from inside your event function, creating a closure. The effect of this is that any accessing of the variable numQuestions inside your event functions references the variable as it was from the moment your javascript interpreter came across the event function itself- ie, the first time you play your game.
Have a look at these to get an idea of where it's going wrong.
It sounds like you need to instantiate a new Game object when the game is restarted.
Where do you define the on click listener? If it triggers two times, it seems like you are defining the on click listener in such way, that after you completed one game and start all over, a new listener will be registered so you got 2 in the end.

How to make a javascript slideshow using for loop

I want to make a javascript slideshow using a for loop
Javascript code
var Image_slide = new Array("img1.jpg", "img2.jpg", "img3.jpg");// image container
var Img_Lenght = Image_slide.length; // container length - 1
function slide(){
for (var i = 0; i < Img_Lenght; i++) {
Image_slide[i];
};
document.slideshow.src = Image_slide[i];
}
function auto(){
setInterval("slide()", 1000);
}
window.onload = auto;
html code
<img src="img1.jpg" name="slideshow">
i can't figure out what is the problem of this code it just run img3 continuously without looping img1 and it also skip img2 from the loop
The better option to solve this than to use a for loop is to simply skip the for loop all-together. Using a for loop is really too complicated and there's a far simpler solution.
Rather than using a for loop, simply assign the slides directly and keep track of positioning:
var Image_slide = new Array("img1.jpg", "img2.jpg", "img3.jpg");// image container
var Img_Length = Image_slide.length; // container length - 1
var Img_current = 0
function slide() {
if(Img_current >= Img_Length) {
Img_current = 0;
}
document.slideshow.src = Image_slide[Img_current];
Img_current++;
}
function auto(){
setInterval(slide, 1000);
}
window.onload = auto;
Interval should already run anyway. The loop inside the auto is redundant and simply messes it up. You only need to get one array element each time, not the whole loop. Looping through it every time will only return the last result.
You need to keep track of your position and reset the position to 0 once you reach the max length.
I'd also recommend at least 3 seconds for the interval instead of 1 second. One second I think is a bit too fast.
Here's an example of the correct solution on JSFiddle: http://jsfiddle.net/LUX9P/
NOW, that said, the question is actually asking how to make it work with a for loop. I've written up a potential solution to the problem (untested so I can't guarantee it will work), but I HIGHLY ADVISE NOT TO DO IT THIS WAY. It shouldn't be TOO bad overall, its just far more complicated and the solution above is so simple, this solution really isn't worth it.
var Image_slide = new Array("img1.jpg", "img2.jpg", "img3.jpg");// image container
var Img_Length = Image_slide.length; // container length - 1
function slide(){
delay = 0;
start = false;
for (var i = 0; i < Img_Length; i++) {
if(start && delay < 1000) {
delay += 1;
i--;
}
else {
document.slideshow.src = Image_slide[i];
delay = 0;
}
start = true;
}
}
function auto(){
setInterval("slide()", 1000);
}
window.onload = auto;
I cannot guarantee this will work, but essentially, the code I updated in slide() initializes a delay variable and a start variable. When the loop is run through once, it automatically activates start and always sets the first value in source.
Once start has been set, every consecutive time it will increment the delay variable until delay hits 1000, and it will decrement the i variable so that the for loop doesn't increment i over the cap (the length of the array). Basically, it sets i back by one so that the increment in for puts it back to where it should be, preventing it from moving on to the next variable until it finally processes the current entry.
This should, in theory, work. You may need to increase the delay significantly though; that 1000 should not actually equal one second; it'll likely go far faster than that. But I may be mistaken; it might run in one second, I haven't had a chance to try it out yet.
Clearly, the complexity of this is quite high, its just not worth it. My first option should be used instead.

How to trace in the console how many intervals are being executed - JavaScript

I have a problem trying to know if a setInterval() is taking place or it was killed.
I am creating an interval and saving it into a variable:
interval = setInterval('rotate()',3000);
Then on click to an element I stop the interval and wait 10 seconds before starting a new one, by the way the variable interval is global:
$(elm).click(function(){
clearInterval(interval);
position = index;
$('#banner div').animate({
'margin-left':position*(-img_width)
});
setTimeout('startItnerval()',10000);
});
function startItnerval(){
interval = setInterval('rotate()',3000);
}
It seems to work but eventually I can realize that there are intervals still being in place, everytime I start a new interval it is saved in the interval variable, which is global, so in theory even if I start 100 intervals they are all saved in the same variable replacing the previous interval right? So I should only have one instance of interval; then on clearInterval(interval); it should stop any instance.
After looking at the results, apparently even if it is saved in the same variable, they are all separate instances and need to be killed individually.
How can I trace how many intervals are being executed, and if possible identify them one by one? even if I am able to solve the problem I really would like to know if there is a way to count or show in the console how many intervals are being executed?
thanks
jsFiddle Demo
As pointed out in comments, the id's constantly increase as timers are added to a page. As a result, it may be possible to clear all timers running on a page like this:
function clearTimers(){
var t = window.setTimeout(function(){
var idMax = t;
for( var i = 0; i < idMax; i++ ){
window.clearInterval(i);
window.clearTimeout(i);
}
},4);
}
The reason that you can only see one interval is because every time you start a new interval, you overwrite the value in interval. This causes the previous intervals to be lost but still active.
A suggestion would be to just control access to your variable. Clearly there is an issue where the start function is called too often
clearInterval(interval);//when you clear it, null it
interval = null;
and then take advantage of that later
if( interval != null ){
interval = setInterval('rotate()',3000);
}
Also, as Pointy noted in a comment, using a string to call a function is not best practice. What it basically does is converts it into a Function expression which is similar to using eval. You should probably either use the function name as a callback
setInterval(rotate,3000);
or have an anonymous function issue the callback
setInterval(function(){ rotate(); },3000);
setInterval returns an Id, not the actual object, so no, no interval will be overriden if you repeat the line
var xy = setInterval(function() {...}, 1000);
If you want to stop the interval you have to clear it:
clearInterval(xy);
And if your startInterval can be called multiple times in a row, but you don't want to create multiple intervals, just clear the inverval before you start a new one:
function startInterval(){
clearInterval(interval);
interval = setInterval('rotate()',3000);
}
If you have to create multiple intervals, you could save the ids in an array to keep track of them:
var arr = [];
//set the interval
arr.push(setInterval(...));
//get number of currently running intervals
var count = arr.length //gives you the number of currently running intervals
//clear the interval with index i
clearInterval(arr[i]);
arr.splice(i, 1);

Counting down for x to 0 in Javascript?

I have from the backend a time on the format 00:12:54 and I display it to the screen. But, I would like to have this time to continue to go down. I have though to create a variable in javascript that will old the time and with setTimeout to loop to display with document.getElementById the new value. I think it can be problematic if I have many time to go down in same time. I might require an array?
How would you do that? If I have no other suggestion, I will try my way, but I am curious to know if it does have a more secure way to do it.
Do you know jQuery Framework? It's a Javascript framework that have a lot of utilities methods and functions that let you do Javascript stuff more easily.
Here is a count down plugin (haven't tested it).
I suggest you to download JQuery than download the plugin . Check the sample of code from the "relative" tab on the website. You can have something like :
$('#until2d4h').countdown({until: '+12M +54S'});
*The only drawback with what I suggest you is that you will require 2 .js to be added. Try to add them only when needed and you will be find.
General algorithm:
Read time from server.
Read the current time.
Call a function.
In your function, read the current time, get the delta from the initial time you read in step 2.
Subtract the delta from the initial time you read from the server in step 1 and display the remainder.
The function should call window.setTimeout to call itself in 1000ms (or adjust according to time elapsed within the function), if you want to continue counting down.
Here's a rough cut:
window.onload = function () {
var countdown_start_in_ms = 6000; // from server
function tick() {
var now = new Date().getTime();
var disp = start - now;
if (disp < 0) {
disp = 0;
}
var el = document.getElementById("countdown");
el.innerHTML =
// quick hack to format time
/(\d\d:\d\d:\d\d) ...$/.exec(new Date(disp).toUTCString())[1];
if (disp > 1000) {
var elapsed = new Date().getTime() - now;
window.setTimeout(tick, 1000 - elapsed);
} else {
// stop countdown and set color to light grey
el.style.color = "#ccc";
}
}
var start = new Date().getTime() + countdown_start_in_ms;
tick();
}
You won't like the taste of this one, but it'll do you good:
Google for 'javascript timer' and get your hands dirty reading through the various examples and tutorials returned by that search.
You'll learn a lot more than just how to write a count-down timer. :-)
Good luck!
Take a look at Grab hands and set your own time. and inspect its code. While it is written with Dojo, the "clock" part is in plain JavaScript. In your case the only difference is how to advance the counter — decrease rather than increase it.

Categories

Resources