Issue
The error you are encountering is related to how variable scoping operates in Javascript. In JavaScript, variables are scoped to the enclosing function or script. When you attempt to drag the circle, the value of i === 5
from the for loop, causing path[i]
to be undefined (out of range) within the drag function, resulting in an error.
To delve deeper into this "closure inside loop" issue, refer to this answer.
Resolutions
This solution offers some common fixes for this problem.
ES6 Let
The ES6 let
statement serves as a contemporary remedy, bypassing several scope inconsistencies present in the var
statement. With variables scoped to the containing block, each iteration of the loop obtains its independent instance of i
.
To integrate ES6 features into PaperScript, ensure you initially load a newer version of the Acorn parser (credits to sasensi and Geddes). Then, simply declare let i
within 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.")
};
}
See a functional Stackblitz here.
Closure Solution
If you prefer not to modify the PaperScript parser, you can employ a closure to capture the index in a fresh 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);
}
View a working Stackblitz example here.