Skip to content

Instantly share code, notes, and snippets.

@ericdvb
Created August 9, 2018 13:36
Show Gist options
  • Save ericdvb/c650a9681e005b335862c3f477a7f459 to your computer and use it in GitHub Desktop.
Save ericdvb/c650a9681e005b335862c3f477a7f459 to your computer and use it in GitHub Desktop.
Mapbox Component with animation
class MapboxComponent extends React.Component {
async componentDidMount() {
// Some map instantiation
map.on('style.load', () => {
map.addSource('vehicles', {
"type": "geojson",
"buffer": 5,
"data": {
"type": "FeatureCollection",
"features":[]
}
});
map.addLayer({
"id": "vehicles",
"source": "vehicles",
"type": "symbol",
"layout": {
"icon-image": {
"property": "icon_type",
"type": "identity"
},
"icon-size": {
"stops": [
[0, 0.5],
[7, 1]
]
},
"icon-rotate": {
"property": "icon_rotate",
"type": "identity"
},
"icon-ignore-placement": true
}
})
});
}
componentDidUpdate(lastProps, lastState, snapshot) {
const { map } = this;
const { vehicles: stateVehicles } = this.state;
const { vehicles: nextVehicles } = this.props;
const animationLength = 5000;
const animationArray = [{
type: 'location',
duration: 5000,
delay: 500,
}, {
type: 'rotation',
duration: 2000,
delay: 1000,
}];
const animationIndex = 0;
const animateVehicles = (timestamp) => {
if (this.animationStartTime === null) {
this.animationStartTime = timestamp;
}
const elapsedTime = timestamp - this.animationStartTime + animationArray
.slice(0, animationIndex)
.reduce((offset, animation) => offset + animation.duration + animation.delay, 0);
const progress = elapsedTime / animationLength;
const safeProgress = Math.min( progress.toFixed(2), 1);
const nextData = {
"type": "FeatureCollection",
"features": stateVehicles
? stateVehicles.map(getNextVehicleMapCallback(safeProgress))
: []
};
map.getSource('vehicles').setData(nextData);
if (safeProgress !== 1) {
this.animationFrame = requestAnimationFrame(animateVehicles);
}
}
// check whether current position of each vehicle in nextProps matches position in lastProps
// if it doesn't, put currentposition from lastprops in lastposition of nextState
let vehiclesChanged = false;
if (nextVehicles.length > 0 && lastProps.vehicles.length > 0) {
const nextStateVehicles = nextVehicles.map(nextVehicle => {
const matchingLastVehicle = lastProps.vehicles.find(lastVehicle => nextVehicle.device_id === lastVehicle.device_id);
if (matchingLastVehicle) {
if (matchingLastVehicle.latitude !== nextVehicle.latitude
|| matchingLastVehicle.longitude !== nextVehicle.longitude) {
vehiclesChanged = true;
return {
...nextVehicle,
lastLatitude: matchingLastVehicle.latitude,
lastLongitude: matchingLastVehicle.longitude,
bearing: bearing([matchingLastVehicle.longitude, matchingLastVehicle.latitude], [nextVehicle.longitude, nextVehicle.latitude]),
lastBearing: matchingLastVehicle.bearing,
};
}
return {
...nextVehicle,
lastLatitude: matchingLastVehicle.latitude,
lastLongitude: matchingLastVehicle.longitude,
bearing: bearing([matchingLastVehicle.longitude, matchingLastVehicle.latitude], [nextVehicle.longitude, nextVehicle.latitude]),
lastBearing: bearing([matchingLastVehicle.longitude, matchingLastVehicle.latitude], [nextVehicle.longitude, nextVehicle.latitude])
};
}
return nextVehicle;
});
if (vehiclesChanged) {
this.setState({
vehicles: nextStateVehicles,
changedBySetState: true,
}, () => {
if (stateVehicles) {
cancelAnimationFrame(this.animationFrame);
const elapsedTime = performance.now() - this.animationStartTime;
if (elapsedTime < animationLength) {
const source = map.getSource('vehicles');
if (source._data.features.length > 0) {
source.setData({
"type": "FeatureCollection",
"features": stateVehicles
? stateVehicles.map(vehicle => {
const matchingVehicle = source._data.features.find(tweeningVehicle => tweeningVehicle.id === vehicle.id)
return {
"type": "Feature",
"properties": {
"id": vehicle.device_id,
"status": vehicle.status,
"type": vehicle.type
},
"geometry": {
"type": "Point",
"coordinates": matchingVehicle.geometry.coordinates
}
}})
: []
})
}
}
this.animationStartTime = null;
this.animationFrame = requestAnimationFrame(animateVehicles);
}
});
}
} else if (nextVehicles.length > 0 && lastProps.vehicles.length === 0);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment