paperJS (paper.js) JavaScript Library walk through by Brett Paufler -
9-10-13
JavaScript Tutorial & paper.js primer
Pendulum Animation (review)
See the Compound Pendulum Tutorial if interested in how this graphic was made. Or the below, should be enough for many.
// All this was pulled line for line from the Pendulum Tutorial
var myStar = [];
var hSS = halfSquareScreen;
for (i = 1; i <= 13; i++){
myStar[i] = Path.Star(CP, 5 + i, hSS/(4 * i), 1);
myStar[i].strokeColor = 'black';
}
myStar[13].strokeColor = 'blue';
//myStar[10].strokeWidth = 3;
for (i = 2; i <= 13; i++){
myStar[i].position = myStar[i - 1].firstSegment.point;
}
function animateObjects(){
//testCircle.position.y += 1;
for (i = 1; i <= 13; i++){
myStar[i] = myStar[i].rotate(i * Math.pow(-1, i));
}
for (i = 2; i <= 13; i++){
myStar[i].position = myStar[i - 1].firstSegment.point;
}
}
Since, I pulled this in wholesale, the only real problem was in
remembering to comment out the default animateObject() function.
But luckily, since that ran, and the circle dropped, it jogged my
memory that it was there. Do you really need an example of
commenting out an outdated function? Eh, it's as easy to include
as not:
// This is the default animateObjects function that I had to comment out
//function animateObjects(){
// testCircle.position.y += 1;
//}
paper.js contains method = Path.contains(point)
Counter intuitively, as some point, I tend to code from the bottom up.
I code this first:
function onMouseDown(event){
testMouseClick(event);
checkClickBox(event);
updateFeedbackPointText(event);
}
But, the checkClickBox(event); will only throw an error on my debugger
(JSLint in Notepad++) until I create that function, so while I am coding
the previous, I insert an empty function call into my code:
function checkClickBox(event){}
Also, note: I pulled the updateFeedbackPointText(event);
function into the onMouseDown(event) function, so that event (rather
than the onFrame(event) is the event the PointText's will track).
Got that? This rather than that.
Of course, a few minutes later, I came back and filled out the
checkClickBox() function:, which I'll use over and over again for these
sandbox tutorials, so at some point I'm going to have to update my
default page to include this.
function checkClickBox(event){
for (i = 1; i <= 6; i++){
if (clickBox[i].contains(event.point)){
switch (i){
case 1:
addStar();
break;
case 2:
deleteStar();
break;
case 3:
addStar();
break;
case 4:
deleteStar();
break;
case 5:
addStar();
break;
case 6:
deleteStar();
break;
} // end switch
} // end contains if
} // end for
} // end checkClickBox function
This function includes two new function calls, so I create those at the same time, as well:
function addStar(){}
function deleteStar(){}
I insert these functions above the checkClickBox() function. Order is important.
Once the switch statement looks like its up and running (no errors,
program doesn't crash, still works as I want it to), I filled out the
two new functions. First, the deleteStar() function, as that one is
easier:
function deleteStar(){
if (visibleStars >= 2){
myStar[visibleStars].visible = false;
visibleStars -= 1;
myStar[visibleStars].strokeColor = 'blue';
}
}
And then the addStar() function,
function addStar(){
if (visibleStars <= 12){
myStar[visibleStars].strokeColor = 'black';
visibleStars += 1;
myStar[visibleStars].visible = true;
myStar[visibleStars].strokeColor = 'blue';
}
}
For both, I use a new variable to track the number of visible objects:
var visibleStars = 13;
I would point out:
- The checkClickBox(event) function is nice and long with plenty of
nested structures, so as each layer is closed out, I comment which
layer is closing.
- All I'm doing with the deleteStar() and addStar() functions is
changing one of the myStar[] Objects from visible to invisible (true or
false, or vice a versa) and altering which myStar[] is to appear blue.
- I am not adding or deleting any objects; that's more complicated and something to be avoided.
And since this is supposed to be a lesson on contains, I should go back
and review that code. This being the start of the appropriate function:
function checkClickBox(event){
for (i = 1; i <= 6; i++){
if (clickBox[i].contains(event.point)){
switch (i){
case 1:
addStar();
break;
(etc)...
The for loop cycles through the six clickBox[]'s, checks to see if they
contain the event.point, which since this function is being called by:
function onMouseDown(event){
testMouseClick(event);
checkClickBox(event);
updateFeedbackPointText(event);
}
The event in question is the mouseClick, onMouseDown(event).
If
this event.point is located within one of the checkClickBox's, the code
searches
through a switch/case structure to determine what to do next. And
for ease of readability, modularity, personal sanity, debugging, and
what not, I recommend instructing the program to run a subroutine
function (unless what is to be done is so simple and basic that calling
a function would seem sort of OCD'ish, if you know what I
mean). And then again, if you suffer from OCD, it's
probably a good idea to get into this right habit now (before something
else takes hold), and always call call your switch/case actions as
external
functions. It's just easier to write, read, and debug.
event.point
And from there, it's time for me to plot values into the
PointText's and see what there is to see.
As previously stated, all of these events are derived from the onMouseDown(event).
And because of this, this is where I finally discovered what I was
doing wrong in regards to events. You see, to 'initialize' the
values of the PointText graphics, I was calling the updateFeedbackPointText();
imediately after I had created that function, but before an
onMouseDown(event) was ever called. No onMouseDown(event), meant no
event for the updateFeedbackPointText() function, and so it was a blind
call and crashing the program.
So, now, when the page loads, all of the FBText[] PointText objects
have the default text from when they were initialized from within the
PointText creation for loop, namely: 'FBText[i] nada yet'.
Interestingly, after the first onMouseDown(event), the program hangs at
event.midPoint. We know it hangs at this point in the code as the
PointText's do not
resolve past this line. This will be something to keep in mind
later. And perhaps a master level programmer would wrap all
events in a try/catch block for this very reason as a way of avoiding
unforeseen difficulties. But for now, I'm just going to make a
mental note of the peculiarity:
- Until created by a mouseHandler function, events are ill-defined (if at all)
That is to say until one of the pre-created functions (onFrame(), onMouseDown(), etc.) kicks off an event, event has little meaning. And since event.middlePoint
identifies the midPoint between two events, that property isn't set
(not even as a Null, undefined, or anything -- hence why the program is
crashing) until two events have been triggered.
And that, I do believe, is the piece of the puzzle I was missing to understand events.
Next up, the remainder of the onMouseFunctions: onMouseUp, onMouseDrag, etc.
previous (CompoundPendulum) paper.js tutorial
index next - onMouseFunctions()
Back to BrettCode Home
Brett Words
my writing site (Home to the writing of Celli the Happy Go Lucky
Celaphopod, Eddie Takosori, Fritz Heinmillerstein, Morgan Feldstone,
Kevin Stillwater, and of course, me, your host, Brett Paufler)
paper.js official site = http://www.paperJS.org
© Copyright 2013 Brett Paufler