Skip to content

Tracking points

Module Trackers

Single point

Tracking an x, y Point over time is common for working with gestures - be it touch gestures on a screen, or movements of limbs in space.

Trackers.point keeps track of a single point, returning an instance of Trackers.PointTracker .

import { Trackers } from 'https://unpkg.com/ixfx/dist/bundle.js';
// Keep track of the last 10 points
const t = Trackers.point({
sampleLimit: 10
})

Call seen() whenever there is a point to track, for example, based on a ‘pointermove’ event.

const info = t.seen(event);
// 'info' looks like: { fromInitial, fromLast, values }

seen() returns Type Trackers.PointTrackerResults - { fromInitial, fromLast, values } - which can be used for comparing the latest point with the initial point or the last point. values is a set of all the recorded points, fromInitial and fromLast yield the relation between the very first seen point and the last point. For both of these, you get:

type PointRelationResult = {
angle: number // in radians
average: Point // average of all points
centroid: Point
distanceFromLast: number
distanceFromStart: number
}

For example:

const { fromInitial, fromLast } = t.seen(pointerEvent); // Add pointer event
// How far away pointer is from the start
const d = fromInitial.fromInitial.distanceFromStart;

In action

In the example below, we start tracking when the pointer is down and add points when there is a pointer move event.

import { Trackers } from 'https://unpkg.com/ixfx/dist/bundle.js';
let tracker = null;
document.addEventListener(`pointerdown`, evt => {
// Init new tracker
tracker = Trackers.point();
tracker.seen({ x: evt.x, y: evt.y });
});
document.addEventListener(`pointermove`, evt => {
if (!tracker) return;
const info = tracker.seen({x: evt.x, y: evt.y });
console.log(`Angle from start: ${info.fromInitial.angle}`);
});

To get the last result without adding anything:

const nfo = tracker.lastResult;

PointTracker

There are a few additional features of the Trackers.PointTracker :

import { Trackers } from 'https://unpkg.com/ixfx/dist/bundle.js';
const tracker = Trackers.point();
// Distance & angle from initial point
tracker.distanceFromStart(); // number
tracker.angleFromStart(); // number (radians)
// Latest point subtracted from initial point
tracker.difference(); // { x, y }
// Properties
tracker.length; // Total length of all points, connected together
tracker.lines; // Set of Lines connecting points in order
tracker.lineStartEnd; // Line that connects start and end point immediately
tracker.vectorCartesian; // Angle based on initial/last
tracker.vectorPolar; // Angle based on initial/last
tracker.x / tracker.y; // Last x,y

Multiple points

If you want to keep track of several different logical points, for example different touches in a multi-touch gesture, or body parts in TensorFlow, it can be a pain to create and manage several PointTracker instances.

Trackers.points to the rescue! It does all this housekeeping for you. Usage is very similar to the PointTracker, but now we have a TrackedPointMap .

import { Trackers } from 'https://unpkg.com/ixfx/dist/bundle.js';
const t = Trackers.points(); // note the plural!

And then whenever there is new data for a point, call seen(), giving the id of the point, and then the point ({x: .., y: ...}). This could be based on a pointer event, or when new predictions are made by TensorFlow, for example.

t.seen(`nose`, pose[`nose`]);

In the example below, we track each named pointer id.

import { Trackers } from 'https://unpkg.com/ixfx/dist/bundle.js';
const tracker = Trackers.points();
document.addEventListener(`pointermove`, async e => {
// Track a point by its id
const info = await tracker.seen(e.pointerId, { x: e.x, y: e.y });
});

To get data:

tracker.last(); // Iterate last seen {x,y} for each named point
tracker.ids(); // Iterate over point names
tracker.has(`nose`); // true if point has been seen

Under-the-hood, it automatically creates a PointTracker for each named point. This can be retrieved using t.get(id). And then you can use all the single-point tracking features described earlier.

// Get the PointTracker for 'nose'
const noseValue = t.get(`nose`);
noseValue.last; // Last seen { x, y }
noseValue.initial; // Initial { x, y }
noseValue.elapsed; // milliseconds since first seen
noseValue.reset(); // reset this named point
...etc

The pointer scale demo (source) uses numberTracker and pointsTracker.