diff --git a/docs/json/class/Util_Tempo.json b/docs/json/class/Util_Tempo.json index 9868b228..eefcf766 100644 --- a/docs/json/class/Util_Tempo.json +++ b/docs/json/class/Util_Tempo.json @@ -164,11 +164,11 @@ { "comment": "This is a core function that let you specify a rhythm and then define responses by calling the `start` and `progress` functions from the returned object. See [Animation guide](../guide/Animation-0700.html) for more details.\nThe `start` function lets you set a callback on every start. It takes a function ([`ITempoStartFn`](#link)).\nThe `progress` function lets you set a callback during progress. It takes a function ([`ITempoProgressFn`](#link)). Both functions let you optionally specify a time offset and a custom name.\nSee [Animation guide](../guide/animation-0700.html) for more details.", "returns": "ITempoResponses", - "returns_comment": "a object with chainable functions\n", + "returns_comment": "an object with chainable functions\n", "parameters": [ { "name": "beats", - "comment": "a rhythm in beats as a number or array of numbers", + "comment": "a rhythm in beats as a number or an array of numbers", "type": "number | number[]", "default": false } diff --git a/guide/Animation-0700.html b/guide/Animation-0700.html index 1630188c..e8c045a8 100644 --- a/guide/Animation-0700.html +++ b/guide/Animation-0700.html @@ -19,9 +19,9 @@

Animation

-

There are many great javascript animation libraries which you may use alongside Pts. For simple use cases, Pts' Tempo utility class provides an intuitive and lightweight alternative.

-

Animation sequences are commonly implemented as a curated list of tweens played in milliseconds. But what if we take the idea one level higher, and think of it like a dance? Like One-two-three, One-two-three...

-

Let's start by setting the beats. Tempo is usually measured in beats-per-minute (bpm), so there are two ways to initiate a Tempo instance: by setting a bpm, or specifying the duration of a beat in milliseconds.

+

Tempo is a lightweight utility class which helps you create animation sequences intuitively. It's an alternative to many other great animation libraries (which you can use with Pts too).

+

Typically, animation sequences are often implemented as a curated list of tweens in milliseconds. But what if we take the idea one level higher, and treat it like a dance? Like One-two-three, One-two-three...

+

Let's start by counting the beats. Tempo is usually measured in beats-per-minute (bpm), so there are two ways to initiate a Tempo instance: by setting a bpm, or specifying the duration of a beat in milliseconds.

// 120 beats-per-minute, or 500ms per beat
 let tempo = new Tempo( 120 ); 
 
@@ -32,21 +32,22 @@
 
let everyTwo = tempo.every( 2 ); // count every 2 beats
 let everyTen = tempo.every( 10 ); // count every 10 beats
 
-

The every function returns an object with two chainable functions: start(...) and progress(...). The start function lets you set a callback to be triggered at the start of every period. For example:

+

The every function returns an object with two chainable functions: start(...) and progress(...). These functions let you attach custom callback functions that respond to animation events.

+

The start function lets you set a callback to be triggered at the start of every n-beats period. For example:

// at the start of every 2-beats period, do something
 everyTwo.start( (count) => ... )
 
-

The progress function lets you specify a callback during the progress of every period, so you can use it to interpolate values and tween properties.

+

The progress function lets you set a callback during the progress of every n-beats period. The second parameter t always start at 0 and ends at 1 in every period, so you can use it to interpolate values and tween properties.

// during every 10-beats period, do something
 everyTen.progress( (count, t, time, isStart) => ... ) 
 
-

Let's look at an example. Here the tempo is set to 60 BPM (or 1 second per beat), and we design the behaviors as such:

+

Let's look at an example. Here the tempo is set to 60 BPM (or 1 second per beat), and we design the behaviors so that:

  • Every 1 beat, the square's color changes
  • Every 2 beats, the circle's color changes and the rotation completes once

js:tempo_progress

-

Pretty easy to create sychronized animation sequences, right? Let's try a few more example.

+

Pretty easy to create synchronized animation sequences, right? Let's try a few more example.

Variations

Tween: Since the t parameter in progress callback function always go from 0 to 1, we can map its value to a Shaping function and change the tweening style. Another neat trick is to use Num.cycle to map the t value from [0...1] to [0...1...0].

everyTwo.progress( (count, t, time, isStart) => {
@@ -65,13 +66,13 @@ 

Variations

js:tempo_rhythm

Controls

-

It's easy to control the speed of your animation by changing bpm by setting the Tempo.bpm property. This makes it easier to synchronize your animations with music or in specific intervals.

+

By changing bpm by setting the Tempo.bpm property, you can control the speed of your animation. This makes it easier to synchronize your animations with music or at specific intervals.

tempo.bpm = 100; // set new bpm
 tempo.bpm += 20; // make it 20 beats faster per minute
 

Try moving your cursor horizontally to change the bpm in this example:

js:tempo_control

-

There are two ways to stop an animation. You can either add return true in the callback functions, or include a name in the third parameter of start or progress functions.

+

There are two ways to stop an animation. You can either return true within start or progress callback functions, or include a name in the third parameter of the callbacks and then call tempo.stop( name ).

let walking = (count, t) => {
    // ...
    return (count > 5);  // return true will stop this animation
diff --git a/guide/Space-0500.html b/guide/Space-0500.html
index 2ca3ed6c..b11a620b 100644
--- a/guide/Space-0500.html
+++ b/guide/Space-0500.html
@@ -50,7 +50,7 @@ 

Players

} } );
-

Here we add an object that conforms to the IPlayer interface, which defines 4 optional callback functions:

+

Here we add an object that conforms to the IPlayer interface, which defines 4 optional callback functions:

  • start function is called when the space is ready. It includes 2 parameters: bound which returns the bounding box, and space which returns its space.
diff --git a/guide/js/examples/tempo_control.js b/guide/js/examples/tempo_control.js index 385a0bc4..0fb9982e 100644 --- a/guide/js/examples/tempo_control.js +++ b/guide/js/examples/tempo_control.js @@ -7,6 +7,8 @@ let space = new CanvasSpace("#"+demoID).setup({ retina: true, bgcolor: "#e2e6ef", resize: true }); let form = space.getForm(); + // ------- + // Create tempo instance let tempo = new Tempo(120); @@ -16,31 +18,29 @@ return ( count, t ) => { let tt = Shaping.quadraticInOut( t ); // shaping lns[i] = Line.fromAngle( (i===0) ? space.center : lns[i-1].p2, Const.two_pi * tt, space.size.y/s ); - form.strokeOnly( c, 10, "round", "round").line( lns[i] ); + form.strokeOnly( c, 10, "round", "round" ).line( lns[i] ); form.fillOnly( c ).point( lns[i].p2, 20, "circle" ); } }; - tempo.every( 6 ).progress( dials( 0, "#FFF", 4 ) ) tempo.every( 4 ).progress( dials( 1, "#123", 6 ) ) tempo.every( 2 ).progress( dials( 2, "#62E", 8 ) ); // track tempo animation space.add( tempo ); + space.add( (time, ftime) => { let b = Num.clamp( (space.pointer.x - space.center.x)/5, -50, 50 ); tempo.bpm = 100 + Math.floor(b); form.fillOnly("#123").text( [20, 32], `BPM is ${tempo.bpm}`); }); - - // start + // For use in demo page only // Note that `playOnce(200)` will stop after 200ms. Use `play()` to run the animation loop continuously. space.playOnce(200).bindMouse().bindTouch(); - // For use in demo page only if (window.registerDemo) window.registerDemo(demoID, space); })(); \ No newline at end of file diff --git a/guide/js/examples/tempo_progress.js b/guide/js/examples/tempo_progress.js index d5b8bc4b..a3fd672f 100644 --- a/guide/js/examples/tempo_progress.js +++ b/guide/js/examples/tempo_progress.js @@ -7,6 +7,8 @@ let space = new CanvasSpace("#"+demoID).setup({ retina: true, bgcolor: "#e2e6ef", resize: true }); let form = space.getForm(); + // ------- + // Create tempo instance let tempo = new Tempo(60); let colors = ["#62E", "#FFF", "#123"]; @@ -20,18 +22,17 @@ tempo.every( 2 ).progress( (count, t) => { let ln = Line.fromAngle( space.center, Const.two_pi*t - Const.half_pi, space.size.y/3 ); let c = colors[ count%colors.length ]; - form.strokeOnly( c, 10, "round", "round").line( ln ); + form.strokeOnly( c, 10, "round", "round" ).line( ln ); form.fillOnly( c ).point( ln.p2, 20, "circle" ); }); // track tempo animation space.add( tempo ); - // start + // For use in demo page only // Note that `playOnce(200)` will stop after 200ms. Use `play()` to run the animation loop continuously. space.playOnce(200).bindMouse().bindTouch(); - // For use in demo page only if (window.registerDemo) window.registerDemo(demoID, space); })(); \ No newline at end of file diff --git a/guide/js/examples/tempo_rhythm.js b/guide/js/examples/tempo_rhythm.js index 7234b321..0244d48d 100644 --- a/guide/js/examples/tempo_rhythm.js +++ b/guide/js/examples/tempo_rhythm.js @@ -7,6 +7,8 @@ let space = new CanvasSpace("#"+demoID).setup({ retina: true, bgcolor: "#e2e6ef", resize: true }); let form = space.getForm(); + // ------- + // Create tempo instance let tempo = new Tempo(120); let counter = 0; @@ -16,7 +18,7 @@ let tt = Num.cycle( Shaping.cubicInOut( t ) ); // shaping let right = Line.fromAngle( space.center, -tt * Const.half_pi - Const.half_pi, space.size.y/3 ); let left = Line.fromAngle( space.center, Const.pi+Const.half_pi + tt*Const.half_pi, space.size.y/3 ); - form.strokeOnly( "#123", 10, "round", "round").lines( [left, right] ); + form.strokeOnly( "#123", 10, "round", "round" ).lines( [left, right] ); if (start) counter++; let c = (counter % 4 < 2) ? "#62E" : "#0C9" @@ -26,11 +28,10 @@ // track tempo animation space.add( tempo ); - // start + // For use in demo page only // Note that `playOnce(200)` will stop after 200ms. Use `play()` to run the animation loop continuously. space.playOnce(200).bindMouse().bindTouch(); - // For use in demo page only if (window.registerDemo) window.registerDemo(demoID, space); })(); \ No newline at end of file diff --git a/guide/js/examples/tempo_shaping.js b/guide/js/examples/tempo_shaping.js index dee59a18..d3013b4a 100644 --- a/guide/js/examples/tempo_shaping.js +++ b/guide/js/examples/tempo_shaping.js @@ -7,6 +7,8 @@ let space = new CanvasSpace("#"+demoID).setup({ retina: true, bgcolor: "#e2e6ef", resize: true }); let form = space.getForm(); + // ------- + // Create tempo instance let tempo = new Tempo(60); let colors = ["#62E", "#FFF", "#123"]; @@ -21,18 +23,18 @@ let tt = Shaping.elasticOut( t ); // shaping let ln = Line.fromAngle( space.center, Const.two_pi*tt - Const.half_pi, space.size.y/3 ); let c = colors[ count%colors.length ]; - form.strokeOnly( c, 10, "round", "round").line( ln ); + form.strokeOnly( c, 10, "round", "round" ).line( ln ); form.fillOnly( c ).point( ln.p2, 20, "circle" ); }); // track tempo animation space.add( tempo ); + - // start + // For use in demo page only // Note that `playOnce(200)` will stop after 200ms. Use `play()` to run the animation loop continuously. space.playOnce(200).bindMouse().bindTouch(); - - // For use in demo page only + if (window.registerDemo) window.registerDemo(demoID, space); })(); \ No newline at end of file diff --git a/guide/js/examples/tempo_stagger.js b/guide/js/examples/tempo_stagger.js index ad9c17be..ae506a35 100644 --- a/guide/js/examples/tempo_stagger.js +++ b/guide/js/examples/tempo_stagger.js @@ -7,6 +7,8 @@ let space = new CanvasSpace("#"+demoID).setup({ retina: true, bgcolor: "#e2e6ef", resize: true }); let form = space.getForm(); + // ------- + // Create tempo instance let tempo = new Tempo(60); let everyTwo = tempo.every( 2 ); @@ -18,7 +20,7 @@ let dir = (count%2 === 0) ? 1 : -1; let s = (count%2 !== 0) ? Const.pi : 0; let ln = Line.fromAngle( space.center, s + Const.pi * tt * dir, space.size.y/3 ); - form.strokeOnly( c, 10, "round", "round").line( ln ); + form.strokeOnly( c, 10, "round", "round" ).line( ln ); form.fillOnly( c ).point( ln.p2, 20, "circle" ); } }; @@ -29,11 +31,11 @@ // track tempo animation space.add( tempo ); - // start + + // For use in demo page only // Note that `playOnce(200)` will stop after 200ms. Use `play()` to run the animation loop continuously. space.playOnce(200).bindMouse().bindTouch(); - // For use in demo page only if (window.registerDemo) window.registerDemo(demoID, space); })(); \ No newline at end of file diff --git a/guide/md/_0500_Space.md b/guide/md/_0500_Space.md index d248bc26..1444ca1c 100644 --- a/guide/md/_0500_Space.md +++ b/guide/md/_0500_Space.md @@ -45,7 +45,7 @@ space.add( { } ); ``` -Here we add an object that conforms to the [IPlayer](../docs/interfaces/_space_.iplayer.html) interface, which defines 4 optional callback functions: +Here we add an object that conforms to the [IPlayer](../docs/?p=Types_IPlayer) interface, which defines 4 optional callback functions: - `start` function is called when the space is ready. It includes 2 parameters: `bound` which returns the bounding box, and `space` which returns its space. diff --git a/guide/md/_0700_Animation.md b/guide/md/_0700_Animation.md index 6bdf1c7a..ff0763c5 100644 --- a/guide/md/_0700_Animation.md +++ b/guide/md/_0700_Animation.md @@ -1,10 +1,10 @@ # Animation -There are many great javascript animation libraries which you may use alongside Pts. For simple use cases, Pts' [`Tempo`](#link) utility class provides an intuitive and lightweight alternative. +[`Tempo`](#link) is a lightweight utility class which helps you create animation sequences intuitively. It's an alternative to many other great animation libraries (which you can use with Pts too). -Animation sequences are commonly implemented as a curated list of tweens played in milliseconds. But what if we take the idea one level higher, and think of it like a dance? Like One-two-three, One-two-three... +Typically, animation sequences are often implemented as a curated list of tweens in milliseconds. But what if we take the idea one level higher, and treat it like a dance? Like One-two-three, One-two-three... -Let's start by setting the beats. Tempo is usually measured in beats-per-minute (bpm), so there are two ways to initiate a [`Tempo`](#link) instance: by setting a bpm, or specifying the duration of a beat in milliseconds. +Let's start by counting the beats. Tempo is usually measured in beats-per-minute (bpm), so there are two ways to initiate a [`Tempo`](#link) instance: by setting a bpm, or specifying the duration of a beat in milliseconds. ``` // 120 beats-per-minute, or 500ms per beat @@ -21,27 +21,29 @@ let everyTwo = tempo.every( 2 ); // count every 2 beats let everyTen = tempo.every( 10 ); // count every 10 beats ``` -The `every` function returns an object with two chainable functions: `start(...)` and `progress(...)`. The `start` function lets you set a callback to be triggered at the start of every period. For example: +The `every` function returns an object with two chainable functions: `start(...)` and `progress(...)`. These functions let you attach custom callback functions that respond to animation events. + +The `start` function lets you set a callback to be triggered at the start of every *n*-beats period. For example: ``` // at the start of every 2-beats period, do something everyTwo.start( (count) => ... ) ``` -The `progress` function lets you specify a callback during the progress of every period, so you can use it to interpolate values and tween properties. +The `progress` function lets you set a callback during the progress of every *n*-beats period. The second parameter `t` always start at 0 and ends at 1 in every period, so you can use it to interpolate values and tween properties. ``` // during every 10-beats period, do something everyTen.progress( (count, t, time, isStart) => ... ) ``` -Let's look at an example. Here the tempo is set to 60 BPM (or 1 second per beat), and we design the behaviors as such: +Let's look at an example. Here the tempo is set to 60 BPM (or 1 second per beat), and we design the behaviors so that: - Every 1 beat, the square's color changes - Every 2 beats, the circle's color changes and the rotation completes once ![js:tempo_progress](./assets/bg.png) -Pretty easy to create sychronized animation sequences, right? Let's try a few more example. +Pretty easy to create synchronized animation sequences, right? Let's try a few more example. ### Variations @@ -76,7 +78,7 @@ let custom = tempo.every( [2, 2, 1, 1] ); // Taaa, Taaa, ta-ta. ### Controls -It's easy to control the speed of your animation by changing bpm by setting the [`Tempo.bpm`](#link) property. This makes it easier to synchronize your animations with music or in specific intervals. +By changing bpm by setting the [`Tempo.bpm`](#link) property, you can control the speed of your animation. This makes it easier to synchronize your animations with music or at specific intervals. ``` tempo.bpm = 100; // set new bpm tempo.bpm += 20; // make it 20 beats faster per minute @@ -86,7 +88,7 @@ Try moving your cursor horizontally to change the bpm in this example: ![js:tempo_control](./assets/bg.png) -There are two ways to stop an animation. You can either add `return true` in the callback functions, or include a `name` in the third parameter of `start` or `progress` functions. +There are two ways to stop an animation. You can either `return true` within `start` or `progress` callback functions, or include a `name` in the third parameter of the callbacks and then call `tempo.stop( name )`. ``` let walking = (count, t) => { diff --git a/src/Util.ts b/src/Util.ts index 58305ff6..c6f4a2f4 100644 --- a/src/Util.ts +++ b/src/Util.ts @@ -376,9 +376,9 @@ export class Tempo { * The `start` function lets you set a callback on every start. It takes a function ([`ITempoStartFn`](#link)). * The `progress` function lets you set a callback during progress. It takes a function ([`ITempoProgressFn`](#link)). Both functions let you optionally specify a time offset and a custom name. * See [Animation guide](../guide/animation-0700.html) for more details. - * @param beats a rhythm in beats as a number or array of numbers + * @param beats a rhythm in beats as a number or an array of numbers * @example `tempo.every(2).start( (count) => ... )`, `tempo.every([2,4,6]).progress( (count, t) => ... )` - * @returns a object with chainable functions + * @returns an object with chainable functions */ every( beats:number|number[] ):ITempoResponses { let self = this;