A lot of movements require waiting for one segment to finish before starting another. Some segments should only be fired at certain times, as well. The best way to handle these timings and communication systems is by using Johnny-Five's animation
events.
We tap into these events by assigning callbacks to special attributes on segments. Let's go into the details of each one and see when they will fire.
In order to understand how the events work and what they can be used for, let's start on our final project: grab your LCD from Chapter 4, Using Specialized Output Devices, and your servo array from earlier in the chapter, and let's build.
Using the following diagrams, build your project; the first diagram is for I2C LCD displays:
The second diagram is for standard LCD displays:
Once you've wired it up, you'll notice that we can modify the last piece of code we wrote to include our LCD and create functions for each event. Let's add the following to our segment: a callback for each event type that prints to the LCD segment [event name]!
.
When you've added the LCD code and the event callbacks, your code should look like this. Let's create a new file called animation-events.js
for this:
var five = require('johnny-five') var board = new five.Board() board.on('ready', function(){ var servos = new five.Servos([3, 5, 6]) var animation = new five.Animation(servos) //For I2CLCDs, uncomment these lines: // var lcd = new five.LCD({ // controller: 'PCF8574A' // }) //NOTE: for standard LCDs, uncomment these lines: // var lcd = new five.LCD({ // pins: [8, 9, 10, 11, 12, 13] // }) var mySegment = { easing: 'inOutCirc', duration: 3000, cuePoints: [0, .25, .75, 1], keyFrames: [ [{degrees: 45}, 45, 45, -45], [{degrees: 30}, 30, 30, 30], [{degrees: 20}, 40, 40, 40] ], onstart: function(){ lcd.clear() lcd.print('Segment started!') }, onpause: function(){ lcd.clear() lcd.print('Segment paused!') }, onstop: function(){ lcd.clear() lcd.print('Segment stopped!') }, onloop: function(){ lcd.clear() lcd.print('Segment looped!') }, oncomplete: function(){ lcd.clear() lcd.print('Segment completed!') } } this.repl.inject({ lcd, animation, mySegment }) animation.enqueue(mySegment) })
Let's try this out! Go ahead and run this with the following:
node events-project.js
You should see Segment started! as soon as the program starts—this is because we enqueue the segment right away. Once it's done, you should see Segment Complete!.
To test onloop
, onpause
, and onstop
, let's modify our segment to run on a loop and enqueue it:
>mySegment.loop = true >animation.enqueue(mySegment)
You should see the start
event, then if you let it run for a bit, it'll show Segment looped!.
Now let's pause it to see the pause
event:
>animation.pause()
You should see Segment paused!. Let's re-run it, then stop to see the onstop
event:
>animation.play() >animation.stop()
You should see Segment stopped!.