Reputation: 10798
In the following code the drawFunc is not executed during the loop (I can see that with a step-by-step-debugging, the code just jumps to the end of the function).
The function gets executed at the line "stage.add(layer);", causing a bug.
Any help on how to fix this?
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
canvas {
border: 1px solid #9C9898;
}
</style>
<script type="text/javascript" src="http://www.html5canvastutorials.com/libraries/kinetic-v3.9.7.js"></script>
<script>
window.onload = function() {
// global parameters
var curvatureX = 10;
var curvatureY = 10;
var nodeRadius = 10;
var stage = new Kinetic.Stage({
container: "container",
width: 578,
height: 300
});
var layer = new Kinetic.Layer();
var nodes = [];
for (var i = 0;i<10;i++){
nodes[i] = new Kinetic.Circle({
x: i*20,
y: i*5,
z:1,
radius: nodeRadius,
fill: "blue",
stroke: "black",
strokeWidth: 4
});
layer.add(nodes[i]);
}
var edges = [];
for (var i = 0;i<9;i++){
console.log("just after the for: "+i);
edges[i]= new Kinetic.Shape({
// *** PROBLEMS IS HERE
// *** FOR LOOP SKIPS THE FOLLOWING LINES
drawFunc: function() {
var context = this.getContext();
context.beginPath();
console.log("in the drawing function: "+i);
context.moveTo(nodes[i].getX(), nodes[i].getY());
if ((nodes[i].getY()-nodes[i+1].getY())<0){
context.quadraticCurveTo((nodes[i].getX()+nodes[i+1].getX()+curvatureX)/2, (nodes[i].getY()+nodes[i+1].getY()-curvatureY)/2, nodes[i+1].getX(), nodes[i+1].getY());
}
else{
context.quadraticCurveTo((nodes[i].getX()+nodes[i+1].getX()+curvatureX)/2, (nodes[i].getY()+nodes[i+1].getY()+curvatureY)/2, nodes[i+1].getX(), nodes[i+1].getY());
}
context.lineWidth = 10;
// line color
context.strokeStyle = "black";
context.stroke();
},
// *** LOOP RESUMES HERE
fill: "#00D2FF",
stroke: "black",
strokeWidth: 4
});
layer.add(edges[i]);
}
//*** FUNCTION IS EXECUTED HERE, CAUSING BUG.
stage.add(layer);
var amplitude_1 = 100;
var amplitude_2 = 30;
var period = 2000;
// in ms
var centerX = stage.getWidth() / 2;
var centerY = stage.getHeight() / 2;
stage.onFrame(function(frame) {
for (var i=0;i<nodes.length;i++){
nodes[i].setX(amplitude_1 * i * Math.sin(frame.time * 2 * Math.PI / period) + centerX);
nodes[i].setY(amplitude_2 * i+ 20);
}
layer.draw();
});
stage.start();
};
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
Upvotes: 0
Views: 487
Reputation: 339917
You cannot use a variable declared outside a function and assume that its value when used inside that function is what it was at the time the function was declared.
In the particular case of a loop variable, that variable will have the last value assigned to it by the time the inner function is called.
To fix this, you have to "close" the outer variable's value inside a new scope, in your case that would look like this:
for (var i = 0; i < 9; ++i) {
...
drawFunc: (function(i) { // <------------+
return function() { // |
alert(i); // you can use this "i" here
}
})(i)
}
The unusual looking construct now there is an immediately invoked function expression which has been passed your loop variable i
, but now has a locally bound copy of that variable in its scope.
Upvotes: 1