JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 76
  • Score
    100M100P100Q63633F
  • License MIT

Animation loop + Event emitter

Package Exports

  • tikki
  • tikki/dist/tikki.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (tikki) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Tikki

Tikki is a fusion of a minimalistic animation loop and an event emitter. It's meant for situations where you need to control the execution flow of different phases within an animation loop, e.g. if you want to batch DOM reads and writes for better performance or orchestrate different tasks within a game loop.

In practice this means that you can use Tikki like an event emitter with the exception that there is no emit method. Instead, Tikki provides a tick() method which emits all the registered events in a batch. You can fully control the execution order of the events at any time.

By default Tikki will automatically tick (using requestAnimationFrame) whenever there are event listeners and will also automatically stop ticking when there are none. However, you can also turn off the auto-tick mode and just call tick() manually if need be.

  • Small footprint (around 700 bytes gzipped).
  • Works in Browser and Node.js.
  • One (tiny) dependency -> Eventti.
  • Written in TypeScript.
  • MIT licensed.

Install

Node

npm install tikki

Browser

<script src="eventti.umd.js"></script>
<script src="tikki.umd.js"></script>

You can access Tikki via window.tikki global variable in browser context.

Usage

import { Ticker } from 'tikki';

// Create a ticker instance and define initial phases.
const ticker = new Ticker({ phases: ['a', 'b', 'c'] });

// Bind some listeners. As long as the ticker has listeners it will be
// automatically ticking unless paused with .stop() method.
const refA = ticker.on('a', () => console.log('a'));
const refB = ticker.on('b', () => console.log('b'));
const refC = ticker.on('c', () => console.log('c'));

// If you want to change the order of phases you can just directly manipulate
// the ticker.phases like this, whenever you like. Note that you can add the
// same phase multiple times in the array.
ticker.phases = ['c', 'b', 'a', 'c'];

// Removing listeners is as simple as this.
ticker.off('a', refA);

// .once method will add a listener that's called only once on the next tick.
ticker.once('a', () => console.log('a'));

// You can always manually start and stop ticking, if needed.
ticker.start();
ticker.stop();

API

Ticker

Ticker is a constructor function which creates a ticker instance when instantiated with the new keyword. When using with TypeScript it's recommended to provide the allowed phases.

import { Ticker } from 'tikki';

// Define all the allowed phases.
type AllowedPhases = 'read' | 'write' | 'foo' | 'bar';

// Instantiate ticker.
const ticker = new Ticker<AllowedPhases>(
  // Optionally, you can provide initial settings.
  {
    // Defaults to an empty array if omitted in which case nothing gets emitted
    // on tick. You should probably always define the phases unless you
    // you intentionally want to skip emitting anything.
    phases: ['read', 'write'],
    // Defaults to true if omitted. If this is set to false then you have to
    // manually call the tick method within your custom loop.
    autoTick: true,
    // You can provide your own requestAnimationFrame function here. Defaults to
    // requestAnimationFrame in browser and a setTimeout based fallback in
    // node.js.
    raf: (callback) => setTimeout(() => callback(Date.now()), 1000 / 60),
    // You can provide your own cancelAnimationFrame function here. Defaults to
    // cancelAnimationFrame in browser and a setTimeout based fallback in
    // node.js.
    caf: (requestId) => clearTimeout(requestId),
  }
);

// You can update phases and autoTick options after instantiation.
ticker.phases = ['foo', 'read', 'write', 'bar'];
ticker.autoTick = false;

Methods

ticker.on( phase, listener )

Add a listener to a phase. You can add the same listener multiple times.

Arguments

  • phase  —  String / Number / Symbol
    • The phase specified as a string, number or symbol.
  • listener  —  Function
    • A listener function that will be called on tick.

Returns  —  Symbol

A listener id, which can be used to remove this specific listener.

Examples

import { Ticker } from 'tikki';

const ticker = new Ticker({ phases: ['test'] });

const a = () => console.log('a');
const b = () => console.log('b');

const id1 = ticker.on('test', a);
const id2 = ticker.on('test', b);
const id3 = ticker.on('test', a);
const id4 = ticker.on('test', b);

ticker.emit('test');
// a
// b
// a
// b

ticker.off('test', id2);
ticker.emit('test');
// a
// a
// b

ticker.off('test', a);
ticker.emit('test');
// b

ticker.once( phase, listener )

Add a one-off listener to a phase. You can add the same listener multiple times.

Arguments

  • phase  —  String / Number / Symbol
    • The phase specified as a string, number or symbol.
  • listener  —  Function
    • A listener function that will be called on tick.

Returns  —  Symbol

A listener id, which can be used to remove this specific listener.

Examples

import { Ticker } from 'tikki';

const ticker = new Ticker({ phases: ['test'] });
const a = () => console.log('a');
const b = () => console.log('b');

ticker.on('test', a);
ticker.once('test', b);

ticker.emit('test');
// a
// b

ticker.emit('test');
// a

ticker.off( [phase], [target] )

Remove a phase listener or multiple phase listeners. If no target is provided all listeners for the specified phase will be removed. If no phase is provided all listeners from the ticker will be removed.

Arguments

  • phase  —  String / Number / Symbol  —  optional
    • The phase specified as a string, number or symbol.
  • target  —  Function / Symbol  —  optional
    • Target removable listeners by specific function or listener id. If no target is provided all listeners for the specified phase will be removed.

Examples

import { Ticker } from 'tikki';

const ticker = new Ticker({ phases: ['test'] });

const a = () => console.log('a');
const b = () => console.log('b');

const id1 = ticker.on('test', a);
const id2 = ticker.on('test', b);
const id3 = ticker.on('test', a);
const id4 = ticker.on('test', b);

// Remove specific listener by id.
ticker.off('test', id2);

// Remove all instances of a specific listener function.
ticker.off('test', a);

// Remove all listeners from a phase.
ticker.off('test');

// Remove all listeners from the ticker.
ticker.off();

ticker.listenerCount( [phase] )

Returns the listener count for a phase if phase is provided. Otherwise returns the listener count for the whole ticker.

Arguments

  • phase  —  String / Number / Symbol
    • The phase specified as a string, number or symbol.

Examples

import { Ticker } from 'tikki';

const ticker = new Ticker({ phases: ['a', 'b', 'c'] });

ticker.on('a', () => {});
ticker.on('b', () => {});
ticker.on('b', () => {});
ticker.on('c', () => {});
ticker.on('c', () => {});
ticker.on('c', () => {});

ticker.listenerCount('a'); // 1
ticker.listenerCount('b'); // 2
ticker.listenerCount('c'); // 3
ticker.listenerCount(); // 6

ticker.tick( time )

The tick method, which you can use to manually tick the ticker.

Arguments

  • time  —  Number
    • Current time in milliseconds.

Examples

import { Ticker } from 'tikki';

const ticker = new Ticker({
  // Disable default auto ticking.
  autoTick: false,
});

// Tick every second.
setInterval(() => {
  ticker.tick(Date.now());
}, 1000);

ticker.start()

Manually start auto-ticking. Note that this method will have no effect if auto ticking is disabled.

Examples

import { Ticker } from 'tikki';

const ticker = new Ticker({ phases: ['a'] });

// Add a listener so ticker starts ticking.
const refA = ticker.on('a', () => console.log('a'));

// Pause ticker for one second every other second.
// Why? For example's sake.
let isPaused = false;
setInterval(() => {
  isPaused = !isPaused;
  if (isPaused) {
    ticker.stop();
  } else {
    ticker.start();
  }
}, 1000);

ticker.stop()

Manually stop auto-ticking. Note that this method will have no effect if auto ticking is disabled.

Examples

import { Ticker } from 'tikki';

const ticker = new Ticker({ phases: ['a'] });

// Add a listener so ticker starts ticking.
const refA = ticker.on('a', () => console.log('a'));

// Pause ticker for one second every other second.
// Why? For example's sake.
let isPaused = false;
setInterval(() => {
  isPaused = !isPaused;
  if (isPaused) {
    ticker.stop();
  } else {
    ticker.start();
  }
}, 1000);

License

Copyright © 2022, Niklas Rämö (inramo@gmail.com). Licensed under the MIT license.