Problem
Your error comes down to the way variable scoping works in Javascript: variables are scoped to the containing function or script. By the time you come along and drag the circle, i === 5
from the for loop, and thus path[i]
is undefined (out of bounds) in the drag function. Hence, your error.
If you would like to learn more, this answer provides an in-depth look into this "closure inside loop" problem.
Solutions
This answer provides some common solutions to this problem.
ES6 Let
The ES6 let
statement is the modern solution to this problem, avoiding many of the scope "quirks" of the var
statement. Variables scope to the containing block, so each pass of the loop gets its own instance of i
.
To use ES6 features within PaperScript, you first need to load a newer version of the Acorn parser (thanks sasensi and Geddes). Then simply declare let i
in the loop:
var path = [];
for (let i = 0; i < 5; i++) {
path[i] = new Path.Circle({
center: view.center,
radius: 30,
fillColor: 'blue'
});
path[i].onMouseDrag = function(event) {
path[i].position += event.delta;
console.log("shape " + i + " is being dragged.")
};
}
Here is a working Stackblitz.
Closure
Without modifying the PaperScript parser, you could use a closure to capture the index in a new function scope:
var path = [];
function createMouseDragHandler(index) {
return function(event) {
path[index].position += event.delta;
console.log("shape " + index + " is being dragged.")
};
}
for (var i = 0; i < 5; i++) {
path[i] = new Path.Circle({
center: view.center,
radius: 30,
fillColor: 'blue'
});
path[i].onMouseDrag = createMouseDragHandler(i);
}
Here is a working Stackblitz.