I am using tracking.js for facedetection and sending the result of facedetection to server through websocket. In the following code in if(event.data.length != 0) of setInterval runs for some iterations even after clearInterval command.Could anyone explain why is it happening?
var mainfunc = setInterval( function() {
ctx.drawImage(video, 0, 0, 400, 300);
tracking.track('#canvas', tracker);
tracker.on('track', function(event){
if (event.data.length != 0 ){
var center_x = event.data[0].x + (event.data[0].width/2);
var center_y = event.data[0].y +(event.data[0].height/2);
var str = center_x + " " + center_y +" " + center_image_x + " " + center_image_y + " " + flag ;
webSocket.send( str );
// dunno why it is executing number of times ??????????
clearInterval(mainfunc);
}
});
} , 0);
The probable reason you're getting multiple executions is that your code is registering "many" event handlers inside the interval callback (tracker.on(... happens in every callback). Then, only when that event arrives with the condition satisfying data do you clear the interval. That's probably a basic flaw in your logic that should be changed. Only register to the 'track' event 1 time.
It looks like there's a missunderstanding how tracking and the setInterval functions.
setInterval is meant to run a piece of code over and over again with a set interval (in milliseconds).
According to the tracking.js' website, you only start the tracking once and it'll keep tracking things.
Try changing your code to this:
var trackerTask = tracking.track('#canvas', myTracker);
myTracker.on('track', function(event){
if (event.data.length != 0 ){
var center_x = event.data[0].x + (event.data[0].width/2);
var center_y = event.data[0].y +(event.data[0].height/2);
var str = center_x + " " + center_y +" " + center_image_x + " " + center_image_y + " " + flag ;
webSocket.send( str );
trackerTask.stop(); // stopping the tracking
}
});
And now I'm not certain but I think you want to continously draw the video feed. You can do this in this way:
function drawVideo() {
requestAnimationFrame(drawVideo); //this will make sure it's redrawn as soon as the browser is ready
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.drawImage(video, 0, 0, 400, 300);
}
drawVideo(); //this call is needed to initiate drawing of the video.
Related
I have a setTimout loop being called repeatedly but the loop seems to catch up with itself and causes sticking on my page ect. I added a alert to see what was happening and i had the timer set to call every 10seconds, but the alert was being displayed oppressively faster until it was continuous
can anybody see why this is by my code below.
Many thanks
$(function(){
var running = setTimeout(function (){
var varLISTID = document.getElementById('datacatch').getAttribute("data-variable-LISTID");
var varUSERACCOUNTNAME = document.getElementById('datacatch').getAttribute("data-variable-USERACCOUNTNAME");
var varITEMACCOUNTNAME = document.getElementById('datacatch').getAttribute("data-variable-ITEMACCOUNTNAME");
var varSELECTEDUSER= document.getElementById('datacatchuser').getAttribute("data-variable-SELECTEDUSER");
var mylink = "loadmessages.php?listID=" + varLISTID + "&useraccountname=" + varUSERACCOUNTNAME + "&itemaccountname=" + varITEMACCOUNTNAME + "&selecteduser=" + varSELECTEDUSER;
$('#infobox1').load(mylink);
var myotherlink = "contactselect.php?listID=" + varLISTID + "&useraccountname=" + varUSERACCOUNTNAME + "&itemaccountname=" + varITEMACCOUNTNAME + "&selecteduser=" + varSELECTEDUSER;
$('#containercontact').load(myotherlink);
},10000);//10s
$(document).keypress(function() {
clearInterval(running);
})
});
I've built a custom, dirt and quick, jQuery/JavaScript slider... which works great, except for one issue.
When using the 'Previous' button, it works perfectly the first time you click it, but then when you click it again, the length of the array becomes '2' when it should be '1' because there are only two results...
Code:
jQuery("#sliderNext").click(function(event) {
$("#sliderNext").fadeOut(50);
$("#sliderPrevious").fadeOut(50);
setTimeout(function() {
$("#sliderNext").fadeIn(100);
$("#sliderPrevious").fadeIn(100);
}, 900);
slideNumber++;
if(slideNumber < image.length && caption.length) {
jQuery(".slider-image").css("background-image", "url(" + image[slideNumber] + ")");
jQuery("#caption").text(caption[slideNumber]);
console.log("if: " + slideNumber);
}
else
{
slideNumber = 0;
jQuery(".slider-image").css("background-image", "url(" + image[slideNumber] + ")");
jQuery("#caption").text(caption[slideNumber]);
console.log("else: " + slideNumber);
}
});
jQuery("#sliderPrevious").click(function(event) {
$("#sliderNext").fadeOut(50);
$("#sliderPrevious").fadeOut(50);
setTimeout(function() {
$("#sliderNext").fadeIn(100);
$("#sliderPrevious").fadeIn(100);
}, 900);
slideNumber--;
console.log(image.length);
if(slideNumber >= 0 && slideNumber <= image.length) {
jQuery(".slider-image").css("background-image", "url(" + image[slideNumber] + ")");
jQuery("#caption").text(caption[slideNumber]);
console.log("if: " + slideNumber);
}
else
{
slideNumber = image.length;
jQuery(".slider-image").css("background-image", "url(" + image[slideNumber] + ")");
jQuery("#caption").text(caption[slideNumber]);
console.log("else: " + slideNumber);
console.log(image.length);
}
});
I've tried using different operators, if/else statements, it always sets it to 2 on the second click.
Could anybody point me in the right direction for why it would do this?
This might be because your click event gets bound the second time to the button and therefore jumps twice.
Try to "unbind" your click events before binding them.
$("#sliderPrevious").unbind();
// and then
jQuery("#sliderPrevious").click(function(event) {...});
Do this to every event that gets bound when intializing the page.
EDIT
var myArray = [a,b];
Note that myArray.length == 2 but myArray[2] is undefined.
Array indexes start at [0] thats why you have to substract 1 from your "counter" variable.
I'm working on this automated, non-endless slideshow, with dynamically loaded content. Each image has to be acompanied by sound. So far I got dynamic loading of both images and sounds down. But it all happens at once, which it shouldn't. I figured, that setTimeout can come in handy here, to set the interval between each pair, but all I got is either last image multiplied by the iteration count or script not working at all. delay also didn't prove to be of any help.
Here's whot I got so far:
function displayImages(data){
var count = data;
var pixBox = $('#picture-box');
var imgPre = 'resources/exhibit-';
var imgExt = '.png';
var sndExt = '.wav';
for(i = 1; i < count; i++) {
var imgSrc = '<img src="' + imgPre + i + imgExt + '">';
var sndSrc = new Audio(imgPre + i + sndExt);
sndSrc.play();
pixBox.append(imgSrc);
}
}
My question is: how to set the setTimeout (or whatever function is the best here), for it to iterate over time. Say, to set the change of img/sound pairs every 2 seconds?
You can use setTimeout like this:
function displayImages(cur, total){
var pixBox = $('#picture-box');
var imgPre = 'resources/exhibit-';
var imgExt = '.png';
var sndExt = '.wav';
var imgSrc = '<img src="' + imgPre + cur + imgExt + '">';
var sndSrc = new Audio(imgPre + cur + sndExt);
sndSrc.play();
pixBox.append(imgSrc);
return setTimeout( 'displayImages(' + ((cur+1)%total) + ',' + total + ')', 2000 );
}
And start it off like this: displayImages(0,total) where total corresponds to your data variable.
The reason I like to use setTimeout and not setInterval in these situations is that setTimeout is only called after the previous function has completed. setInterval can get back-logged and freeze up your page.
Note that the function returns a handle for the timeout. If you should want to stop the animation, you can do this:
var animation = displayImages(0,total);
...some code...
clearTimeout(animation);
and the animation will stop.
You can use a setInterval, this does the same code at every interval.
var myInterval = window.setInterval(displayImages, 2000);
This will make sure your function gets called every 2000 milliseconds.
More information on MDN setInterval
You can try something like this
$(function() {
var count = 100;
var i = 0;
var repeat = setInterval(function() {
if (i <= count) {
var imgSrc = '<img src="' + imgPre + i + imgExt + '">';
var sndSrc = new Audio(imgPre + i + sndExt);
sndSrc.play();
pixBox.append(imgSrc);
i++;
}
else{
i = 0; //reset count if reaches threshold.
}
}, 5000); //5 secs
});
With this, if you want to reset the interval on any event you can simple call
clearInterval(repeat);
See a setInterval example here: JSFiddle
var i = 0;
setInterval(fadeDivs, 3000);
function fadeDivs() {
i = i < images.length ? i : 0;
$('#my-img').fadeOut(200, function(){
$(this).attr('src', images[i]).fadeIn(200);
})
i++;
}
This question already has an answer here:
Why is my window.setInterval function overlapping itself in the DOM when called multiple times?
(1 answer)
Closed 1 year ago.
I'm new to JS, and decided to start of learning by a making a small game. I am using a setInterval to automate the enemy's attack. For their first attack the interval is correct, but after the second attack it speeds up to attacking almost three times, or more, a second. I'm also having trouble stopping the interval once either the player's or the enemy's health reaches 0.
here is pretty much all the code pertaining my problem. The whole code can be found here
function deadFunct(){
if(yourHealth <= 0){
window.alert("You dead");
clearInterval(fightAuto);
clearInterval(deadAuto);
}
if(enemyHealth <= 0){
window.alert("The enemy is dead");
clearInterval(fightAuto);
clearInterval(deadAuto);
}
}
function nextFunct(){
document.getElementById("nextBtn").disabled=true;
document.getElementById("swordBtn").disabled=false;
document.getElementById("bowBtn").disabled=false;
document.getElementById("hamBtn").disabled=false;
var a=Math.random();
if(a>0.66){
enemy="Knight";
eAcc=.75;
eDmg=5;
eAttackSpeed=2000;
y= "Your health = " + yourHealth + " || "+ enemy +" = " + enemyHealth + "<br>";
document.getElementById("attack").innerHTML=y;
}else if(a>0.33){
enemy="Archer";
eAcc=.80;
eDmg=3;
eAttackSpeed=1750;
y= "Your health = " + yourHealth + " || "+ enemy +" = " + enemyHealth + "<br>";
document.getElementById("attack").innerHTML=y;
}else{
enemy="Berserker";
eAcc=.66;
eDmg=7;
eAttackSpeed=2500;
y= "Your health = " + yourHealth + " || "+ enemy +" = " + enemyHealth + "<br>";
document.getElementById("attack").innerHTML=y;
}
}
function enemyAttackFunct(){
for(var i=0; i<1;i++){
if(enemy == "Archer"){
fightAuto = setInterval(function(){aAttackFunct()},eAttackSpeed);
document.getElementById("test").innerHTML=eAttackSpeed;
}else if(enemy == "Knight"){
fightAuto = setInterval(function(){kAttackFunct()},eAttackSpeed);
document.getElementById("test").innerHTML=eAttackSpeed;
}else{
fightAuto = setInterval(function(){bAttackFunct()},eAttackSpeed);
document.getElementById("test").innerHTML=eAttackSpeed;
}
}
}
You keep calling 'setInterval' again again. Each call is running in parallel.
If you have more than one warrior peer type (archer, knight, etc), create an array that will have a separate set interval for each.
If, as seems the case, you only have one and they play at random each turn, add clearInterval before every setInterval
you should never use setInterval for animations!
Just use requestAnimationFrame instead!
https://developer.mozilla.org/en/docs/Web/API/window.requestAnimationFrame
http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
http://css-tricks.com/using-requestanimationframe/
I have to load a very big JSON object and perform various expensive processes. For this reason, I am showing a progress bar which increments a total of five times. If I have to load 10000 items, it will update every 2000 times, etc.
The problem is the effect is not visible because all the stack executes after the entire function is complete, instead of updating the progressbar at every 20% of the process. It doesn't matter if I try to load 10000 items or 2 million items, same stuff happens, and judging by the computation delay between console logs, there is definitely enough processing time to show a visible progress effect. Perhaps I'm not understanding the javascript for(I know this wasn't the way to do it). How do you track an expensive process and make a visible progress bar effect properly?
This is the js file.
login with
username : admin
password: testit
var initItems = function(publicationItems) {
var publications = new Array();
var numberOfItems = goog.object.getCount(publicationItems);
var minStep = 20;
var currentProgress = 20;
var progressBarStep = parseInt(numberOfItems / 5);
var i = 0;
goog.object.forEach(publicationItems, function() {
var currentName = publicationItems.name;
var currentCat = publicationItems.categories;
// Insert clear div to break line after every 5 items.
if (i % 5 == 0 && i != 0)
publications.push(this.clear);
if(i % progressBarStep == 0)
{
progressBar.setValue(currentProgress);
console.log(i + ' ' + progressBarStep + ' ' + currentProgress + ' ' + progressBar.getValue());
currentProgress += minStep;
}
i++;
publications.push(goog.dom.createDom('div', {
'style' : 'width:' + this.currentPublicationDimension + 'px;height:' +
this.currentPublicationDimension + 'px;border:1px solid #B3B3B3;' +
'float: left;margin-top: 5px;background-color: #FCFCFC;' +
'max-width:' + this.currentPublicationDimension + 'px;max-height:' +
this.currentPublicationDimension + 'px;_height:' +
this.currentPublicationDimension +
'px;_width:' + this.currentPublicationDimension + 'px;margin-left:' +
this.publicationLeftMargin + 'px;',
'class' : 'publication'
}, currentName, currentCat));
}, this);
return publications;
};
And the context from where this function was called:
// Bind COMPLETE event listener to ajaxHandler.
goog.events.listen(ajaxHandler, goog.net.EventType.SUCCESS,
goog.bind(function(e) {
//goog.style.showElement(progressBarContainer, false);
goog.dom.append(this.mainViewPublications, initItems.call(this, e.target.getResponseJson()));
}, this), false, this);
The problem is that JavaScript is Singlethreaded and first tries to execute the calculations. The ProgressBar is asynchronous and will only update, if the thread is not busy.
You could use callbacks like following
function a () {
/* do one iteration */
progressBar.setValue(currentProgress);
goog.Timer.callOnce(a, 10);
}
The Problem with that, is that you can't pass parameters to the function and you have to use global variables (or at least 'object' wide variables).
I currently have the same issue and haven't found a really good solution. So this is a first approach. If I find another solution I will update it here.