Why aren't my ball (objects) shrinking/disappearing?

JavascriptHtml

Javascript Problem Overview


http://jsfiddle.net/goldrunt/jGL84/42/ this is from line 84 in this JS fiddle. There are 3 different effects which can be applied to the balls by uncommenting lines 141-146. The 'bounce' effect works as it should, but the 'asplode' effect does nothing. Should I include the 'shrink' function inside the asplode function?

// balls shrink and disappear if they touch
var shrink = function(p) {
    for (var i = 0; i < 100; i++) {
        p.radius -= 1;
    }
    function asplode(p) {
        setInterval(shrink(p),100);
        balls.splice(p, 1);
    }
}

Javascript Solutions


Solution 1 - Javascript

Your code has a few problems.

First, in your definition:

var shrink = function(p) {
    for (var i = 0; i < 100; i++) {
        p.radius -= 1;
    }

    function asplode(p) {
         setInterval(shrink(p),100);
        balls.splice(p, 1);
    }
}

asplode is local to the scope inside shrink and therefore not accessible to the code in update where you are attempting to call it. JavaScript scope is function-based, so update cannot see asplode because it is not inside shrink. (In your console, you'll see an error like: Uncaught ReferenceError: asplode is not defined.)

You might first try instead moving asplode outside of shrink:

var shrink = function(p) {
    for (var i = 0; i < 100; i++) {
        p.radius -= 1;
    }
}

function asplode(p) {
     setInterval(shrink(p),100);
     balls.splice(p, 1);
}

However, your code has several more problems that are outside the scope of this question:

  • setInterval expects a function. setInterval(shrink(p), 100) causes setInterval to get the return value of immediate-invoked shrink(p). You probably want

      setInterval(function() { shrink(p) }, 100)
    
  • Your code for (var i = 0; i < 100; i++) { p.radius -= 1; } probably does not do what you think it does. This will immediately run the decrement operation 100 times, and then visually show the result. If you want to re-render the ball at each new size, you will need to perform each individual decrement inside a separate timing callback (like a setInterval operation).

  • .splice expects a numeric index, not an object. You can get the numeric index of an object with indexOf:

      balls.splice(balls.indexOf(p), 1);
    
  • By the time your interval runs for the first time, the balls.splice statement has already happened (it happened about 100ms ago, to be exact). I assume that's not what you want. Instead, you should have a decrementing function that gets repeatedly called by setInterval and finally performs balls.splice(p,1) after p.radius == 0.

Solution 2 - Javascript

setInterval(shrink(p),100);

This doesn't do what you think it does. This calls shrink, passes it p, and then passes the result to setInterval. shrink(p) returns undefined, so this line doesn't actually put anything on an interval.

You probably want:

setInterval(function(){
    shrink(p)
}, 100);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMattOView Question on Stackoverflow
Solution 1 - JavascriptapsillersView Answer on Stackoverflow
Solution 2 - JavascriptRocket HazmatView Answer on Stackoverflow