tracktracker/front/map.js

152 lines
3.8 KiB
JavaScript

require('ol/ol.css');
const axios = require('axios');
const {Map, View} = require('ol');
const TileLayer = require('ol/layer/Tile').default;
const XYZSource = require('ol/source/XYZ').default;
const VectorLayer = require('ol/layer/Vector').default;
const VectorSource = require('ol/source/Vector').default;
const Feature = require('ol/Feature').default;
const Point = require('ol/geom/Point').default;
const LineString = require('ol/geom/LineString').default;
const proj = require('ol/proj');
const {Style, Fill, Stroke, Circle} = require('ol/style');
const color = require('color');
const mapboxToken = `pk.eyJ1IjoibWF0dGVvZGVsYWJyZSIsImEiOiJja2NxaTUyMmUwcmFhMn\
h0NmFsdzQ3emxqIn0.cyxF0h36emIMTk3cc4VqUw`;
const network = require('../back/data/network.json');
const makeDataSources = async () =>
{
const segmentsSource = new VectorSource();
const stopsSource = new VectorSource();
segmentsSource.addFeatures(
Object.values(network.segments).map(({lines, points}) =>
new Feature({
colors: lines.map(line => network.lines[line].color),
geometry: new LineString(points.map(
({lat, lon}) => proj.fromLonLat([lon, lat])
)),
})
)
);
stopsSource.addFeatures(
Object.values(network.stops).map(({lines, lon, lat}) =>
new Feature({
colors: lines.map(line => network.lines[line].color),
geometry: new Point(proj.fromLonLat([lon, lat])),
})
)
);
return {segmentsSource, stopsSource};
};
const makeBorderColor = mainColor =>
{
const hsl = color(mainColor).hsl();
hsl.color = Math.max(0, hsl.color[2] -= 20);
return hsl.hex();
};
const segmentsBorderStyle = feature => new Style({
stroke: new Stroke({
color: makeBorderColor(feature.get('colors')[0]),
width: 8,
}),
});
const segmentsInnerStyle = feature => new Style({
stroke: new Stroke({
color: feature.get('colors')[0],
width: 6,
}),
});
const stopsStyle = feature => new Style({
image: new Circle({
fill: new Fill({
color: feature.get('colors')[0],
}),
stroke: new Stroke({
color: makeBorderColor(feature.get('colors')[0]),
width: 1.5,
}),
radius: 6,
}),
});
const createMap = async (target) =>
{
// Map background
const backgroundSource = new XYZSource({
url: 'https://api.mapbox.com/' + [
'styles', 'v1', 'mapbox', 'streets-v11',
'tiles', '512', '{z}', '{x}', '{y}',
].join('/') + `?access_token=${mapboxToken}`,
tileSize: [512, 512],
});
const backgroundLayer = new TileLayer({
source: backgroundSource,
});
// Data overlay
const {segmentsSource, stopsSource} = await makeDataSources();
const segmentsBorderLayer = new VectorLayer({
source: segmentsSource,
style: segmentsBorderStyle,
updateWhileInteracting: true,
updateWhileAnimating: true,
});
const segmentsInnerLayer = new VectorLayer({
source: segmentsSource,
style: segmentsInnerStyle,
updateWhileInteracting: true,
updateWhileAnimating: true,
});
const stopsLayer = new VectorLayer({
source: stopsSource,
style: stopsStyle,
minZoom: 13,
updateWhileInteracting: true,
updateWhileAnimating: true,
});
// Setup map
const map = new Map({
target,
layers: [
backgroundLayer,
segmentsBorderLayer,
segmentsInnerLayer,
stopsLayer,
],
view: new View({
center: proj.fromLonLat([3.88, 43.605]),
zoom: 13,
maxZoom: 22,
constrainResolution: true,
}),
});
return map;
};
exports.createMap = createMap;