Tra.js - Reference
Tra.js is a library for visualizing the trajectory of time-series location data in a web browser. Dynamic
changes can be visualized using transition. Currently supports visualization using Canvas element and
D3.js.
Visualized bus trajectories in tokyo, shibuya.
I use processed location data of Shibuya hachiko bus obtained from Shibuya City Open Data.
(https://www.city.shibuya.tokyo.jp/kusei/tokei/opendata/index1.html)
Getting Started
Installation
Download this
OR
npm -i https://github.com/tomoya-onuki/tra.js
Usage
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible"
content="IE=edge">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<script src="tra.min.js"></script>
<title>Tra.js - canvas demo</title>
</head>
<body>
<canvas width="200" height="200"></canvas>
<script>
let data = [];
for (let t = 0, msec = 1000;
t < Math.PI / 2 * 3;
t += Math.PI / 120, msec += 10) {
data.push({
date: msec,
x: Math.cos(t) * 90 + 100,
y: Math.sin(t) * 90 + 100
});
}
const cvs = document.querySelector('canvas');
Trajs()
.trajectory(data)
.weight(5)
.thinning(0.99)
.length(1000)
.damping(0.95)
.color(3, 152, 252)
.ticks(100)
.label('canvas')
.labelStyle({
font: 'Arial',
size: 10,
color: '#000',
offset: 5
})
.canvas(cvs)
.animation(2, 1000, 4000, true);
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible"
content="IE=edge">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<script src="https://d3js.org/d3.v6.js"></script>
<script src="tra.min.js"></script>
<title>Tra.js - d3 demo</title>
</head>
<body>
<div id="d3-view"></div>
<script>
let data = [];
for (let t = 0, msec = 1000;
t < Math.PI / 2 * 3;
t += Math.PI / 120, msec += 10) {
data.push({
date: msec,
x: Math.cos(t) * 90 + 100,
y: Math.sin(t) * 90 + 100
})
}
const svg = d3.select("#d3-view")
.append("svg")
.attr("width", 200)
.attr("height", 200);
Trajs()
.trajectory(data)
.weight(5)
.thinning(0.99)
.length(1000)
.damping(0.95)
.color(3, 152, 252)
.ticks(100)
.label('D3.js')
.labelStyle({
font: 'Arial', size: 10, color: '#000', offset: 5
})
.roundCap(true)
.svg(svg)
.animation(2, 1000, 4000, true);
</script>
</body>
</html>
import { Trajs, Trajectory } from 'trajs';
type Data = {
date: number;
x: number;
y: number;
};
window.onload = () => {
let data: Data[] = [];
for (let t = 0, msec = 1000;
t < Math.PI / 2 * 3;
t += Math.PI / 120, msec += 10) {
data.push({
date: msec,
x: Math.cos(t) * 90 + 100,
y: Math.sin(t) * 90 + 100
});
}
const cvs:HTMLCancasElement =
<HTMLCancasElement>document.querySelector('canvas');
const trajs: Trajectory = Trajs()
.trajectory(data)
.weight(5)
.thinning(0.99)
.length(1000)
.damping(0.95)
.color(3, 152, 252)
.ticks(100)
.label('canvas')
.labelStyle({
font: 'Arial',
size: 10,
color: '#000',
offset: 5
})
.canvas(cvs)
.animation(2, 1000, 4000, true);
}
Data
Describes data structures that can be visualized with Tra.js.
Data is an array of timestamps and 2D coordinate pairs.
Generally, the format of time-series position data is a string for time (e.g. YYYY-MM-DD HH:mm:ss) and
latitude and longitude for coordinates.
However, Tra.js handles time in milliseconds.
Tra.js does not support these conversions. For example, to convert string time to milliseconds, use
Day.js.
Structure
Data must be sorted in ascending order by date.
Date(millis) | lon | lat |
---|---|---|
0 | 10 | 10 |
1000 | 100 | 50 |
... | ... | ... |
Format
Data format is JSON.
[{
date: 0, lon: 10, lat:10
}, {
date: 1000, lon: 100, lat:50
}]
Methods
.trajectory(data: {date: number, lon: number, lat: number}[])
Load a timse-series location data.
.transform({ center : {lon : number, lat : number}, scale : number, projection : string })
Transform cordinate from (lon, lat) into (x, y). A projection is 'liner' or 'mercator'. Default is
'liner'.
.weight(w: number)
Change a trajectory weight. Default is 1.
.thinnign(t: number)
Thin a trajectory width. Default is 1.
.roundCap(r: boolean)
Change a trajectory cap style.
.color(r: number, g: number, b:number)
Change a trajectory color. Format is RGB. Range is [0, 255]. Default is rgb(0,0,0).
.opacity(o: number)
Change a trajectory opacity. Range is [0.0, 1.0]. Default is 1.0.
.damping(d: number)
Damp a trajectory oapcity. Range is [0.0, 1.0]. Default is 1.0.
.length(l: number)
Change a trajectory length. Format is milli second. Default is the difference between the maximum
and
minimum values of date in data.
.ticks(t: number)
Displays tikcs. Format is milli seconds. Range is t > 0. When t ≤ 0, ticks is not displayed.
Default is 0.
.label(l: string)
Displays text on head of trajectory.
.labelStyle({ font: string, size: number, color: string, offset: number })
Change params for display text. Default is {font: "Arial", size: 10, color: '#000000', offset: 0 }.
.canvas(cvs: HTMLCanvasElement)
Set a canvas element.
.svg(svg: SVGElement)
Set a svg element by D3.js.
.draw(date: number)
Draw trajectory and map to given date at the date specified by the argument. Format of date is milli
second.
.animation(frameRate:number, startDate: number, endDate: number, loop: boolean)
Displays an animation of the trajectory from startDate to endDate. The animation repeats when loop
is true.
.start()
Start an animation of trajectory.
.pause()
Stop an animation of trajectory.
.map(topojson: JSON)
Load a map data(.topojson). Map display is available in canvas mode only.
.mapStyle({ color: string, fill: boolean, stroke: boolean })
Set params about map style. Default is {color:'#000', fill: false, stroke: true}.
Example
Canvas
Data
let data = []
for (let t = 0, msec = 1000;
t < Math.PI / 2 * 3;
t += Math.PI / 120, msec += 10) {
data.push({
date: msec,
x: Math.cos(t) * 90 + 100,
y: Math.sin(t) * 90 + 100
});
}
Static
const cvs = document.querySelector('canvas');
Trajs()
.trajectory(data)
.weight(5)
.damping(0.99)
.color(255, 255, 255)
.canvas(cvs)
.draw(3000);
Animation
const cvs = document.querySelector('canvas');
Trajs()
.trajectory(data)
.weight(5)
.thinning(0.99)
.length(1000)
.damping(0.95)
.color(3, 152, 252)
.ticks(100)
.canvas(cvs)
.animation(2, 2, 1000, 4000, true);
Interaction
const cvs = document.querySelector('canvas');
const trajs = Trajs()
.trajectory(data)
.weight(10)
.thinning(0.95)
.length(1000)
.damping(0.9)
.color(242, 169, 51)
.roundCap(true)
.label('text')
.labelStyle({
font: 'Arial', size: 10, color: '#FFF', offset: 5
})
.canvas(cvs)
.animation(2, 1000, 4000, true);
document.querySelector('#start')
.addEventListener('click', function () {
trajs.start();
})
document.querySelector('#pause')
.addEventListener('click', function () {
trajs.pause();
})
Animation (not use transition method.)
const cvs = document.querySelector('canvas');
const ctx = cvs.getContext('2d');
const trajs = Trajs()
.trajectory(data)
.weight(2)
.color(237, 9, 59)
.canvas(cvs)
let start = 1000;
let end = 3000;
let crntDate = start;
setInterval(function () {
ctx.clearRect(0, 0, 200, 200);
trajs.draw(cvs, crntDate);
crntDate++;
if (crntDate > end)
crntDate = start;
}, 1);
Map
fetch("JPN.topojson")
.then(response => response.text())
.then(topojson => {
const cvs = document.querySelector('#cvs');
Trajs()
.canvas(cvs)
.transform({
center: { lon: 137.7, lat: 37.5 },
scale: 500,
projection: 'mercator'
})
.map(topojson, "#fff", false, true)
.draw(0);
})
D3.js
Static
const svg = d3.select("#d3-view")
.append("svg")
.attr("width", 200)
.attr("height", 200);
Trajs()
.trajectory(data)
.weight(5)
.damping(0.99)
.color(255, 255, 255)
.svg(svg)
.draw(3000);
Animation
const svg = d3.select("#d3-view")
.append("svg")
.attr("width", 200)
.attr("height", 200);
Trajs()
.trajectory(data)
.weight(5)
.thinning(0.99)
.length(1000)
.damping(0.95)
.color(3, 152, 252)
.ticks(100)
.label('D3.js')
.labelStyle({
font: 'Arial', size: 10, color: '#FFF', offset: 5
})
.roundCap(true)
.svg(svg)
.animation( 2, 1000, 4000, true);