Published
Edited
Sep 1, 2018
2 forks
15 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
replay;
// update data for one frame
const updateData = (trip, incrementLength, counter, frames) => {
console.log(counter)
// length to visualize for this frame
const frameLength = incrementLength * counter;

// calculate where to place the marker
const pointAlong = turf.along(trip, frameLength);

// cut the line at the point
const lineAlong = turf.lineSplit(trip, pointAlong).features[0];

map.getSource('pointAlong').setData(pointAlong);
map.getSource('lineAlong').setData(lineAlong);
map.flyTo({center: pointAlong.geometry.coordinates});

if (counter === 0) map.getSource('startPoint').setData(pointAlong);
if (counter === frames) {
map.getSource('endPoint').setData(pointAlong);
map.getSource('pointAlong').setData({
type: 'FeatureCollection',
features: [],
});
}
}

const animateTrip = (trip) => {

const { pickuptime, dropofftime } = trip.properties
// calculate real world duration of trip
const start = moment(pickuptime);
const end = moment(dropofftime);
const duration = end.diff(start, 'seconds');
const multiplier = 300;
const vizDuration = duration * (1 / multiplier)
const fps = 25

const frames = parseInt(fps * vizDuration);

console.log(`Trip Duration is ${duration} seconds`)
console.log(`Viz Duration is ${vizDuration} seconds`)
console.log(`Total Frames at ${fps}fps is ${frames}`)

// divide length and duration by number of frames
const tripLength = turf.length(trip);
const incrementLength = tripLength / frames;
const interval = (vizDuration / frames) * 1000;

// updateData at the calculated interval
let counter = 0
console.log(frames)
const dataInterval = setInterval(() => {
updateData(trip, incrementLength, counter, frames)
if (counter === frames + 1) {
clearInterval(dataInterval)
} else {
counter += 1;
}
}, interval)
}
// Create the \`map\` object with the mapboxgl.Map constructor, referencing
// the container div
const map = new mapboxgl.Map({
container,
center: [
-73.9661, 40.7823
],
zoom: 14,
scrollZoom: false,
style: 'mapbox://styles/mapbox/light-v9',
});
map.on('style.load', () => {
const dummyGeojson = {
type: 'FeatureCollection',
features: []
}

map.addSource('lineAlong', {
type: 'geojson',
data: dummyGeojson
});

map.addLayer({
id: 'lineAlong',
type: 'line',
source: 'lineAlong',
paint: {
'line-width': 5,
'line-color': 'steelblue',
'line-opacity': 0.6,
}
})

map.addSource('pointAlong', {
type: 'geojson',
data: dummyGeojson,
});

map.addLayer({
id: 'pointAlong',
type: 'circle',
source: 'pointAlong',
paint: {
'circle-color': 'yellow',
'circle-stroke-width': 0.5,
'circle-stroke-color': '#444',
}
});

map.addSource('startPoint', {
type: 'geojson',
data: dummyGeojson,
});

map.addLayer({
id: 'startPoint',
type: 'circle',
source: 'startPoint',
paint: {
'circle-color': 'green',
'circle-stroke-width': 0.5,
'circle-stroke-color': '#444',
}
});

map.addSource('endPoint', {
type: 'geojson',
data: dummyGeojson,
});

map.addLayer({
id: 'endPoint',
type: 'circle',
source: 'endPoint',
paint: {
'circle-color': 'red',
'circle-stroke-width': 0.5,
'circle-stroke-color': '#444',
}
});
// get a random trip
const oneTrip = rawData.features[3]
animateTrip(oneTrip)
})
// Be careful to clean up the map's resources using \`map.remove()\` whenever
// this cell is re-evaluated.
try {
yield map;
yield invalidation;
} finally {
map.remove();
}
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more