aboutsummaryrefslogtreecommitdiff
path: root/modern/src/map/Map.js
diff options
context:
space:
mode:
authorAnton Tananaev <anton.tananaev@gmail.com>2020-10-24 16:42:29 -0700
committerAnton Tananaev <anton.tananaev@gmail.com>2020-10-24 16:42:29 -0700
commite9f0913d2b1b66764931b6c1235877a44e72890b (patch)
tree404241616fcd340dd5b8b16e699ac8c1e1be2bf1 /modern/src/map/Map.js
parent7806cb2d725ab1aa4f66db86bc376a027dda6df5 (diff)
downloadetbsa-traccar-web-e9f0913d2b1b66764931b6c1235877a44e72890b.tar.gz
etbsa-traccar-web-e9f0913d2b1b66764931b6c1235877a44e72890b.tar.bz2
etbsa-traccar-web-e9f0913d2b1b66764931b6c1235877a44e72890b.zip
Refactor map implementation
Diffstat (limited to 'modern/src/map/Map.js')
-rw-r--r--modern/src/map/Map.js81
1 files changed, 81 insertions, 0 deletions
diff --git a/modern/src/map/Map.js b/modern/src/map/Map.js
new file mode 100644
index 0000000..fec8d50
--- /dev/null
+++ b/modern/src/map/Map.js
@@ -0,0 +1,81 @@
+import 'mapbox-gl/dist/mapbox-gl.css';
+import mapboxgl from 'mapbox-gl';
+import React, { useRef, useLayoutEffect, useEffect, useState } from 'react';
+import { deviceCategories } from '../common/deviceCategories';
+import { loadIcon, loadImage } from './mapUtil';
+
+const element = document.createElement('div');
+element.style.width = '100%';
+element.style.height = '100%';
+
+export const map = new mapboxgl.Map({
+ container: element,
+ style: {
+ version: 8,
+ sources: {
+ osm: {
+ type: 'raster',
+ tiles: ["https://tile.openstreetmap.org/{z}/{x}/{y}.png"],
+ tileSize: 256,
+ attribution: '© <a target="_top" rel="noopener" href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
+ },
+ },
+ glyphs: 'https://cdn.traccar.com/map/fonts/{fontstack}/{range}.pbf',
+ layers: [{
+ id: 'osm',
+ type: 'raster',
+ source: 'osm',
+ }],
+ },
+});
+
+map.addControl(new mapboxgl.NavigationControl());
+
+let readyListeners = [];
+
+const onMapReady = listener => {
+ if (!readyListeners) {
+ listener();
+ } else {
+ readyListeners.push(listener);
+ }
+};
+
+map.on('load', async () => {
+ const background = await loadImage('images/background.svg');
+ await Promise.all(deviceCategories.map(async category => {
+ const imageData = await loadIcon(category, background, `images/icon/${category}.svg`);
+ map.addImage(category, imageData, { pixelRatio: window.devicePixelRatio });
+ }));
+ if (readyListeners) {
+ readyListeners.forEach(listener => listener());
+ readyListeners = null;
+ }
+});
+
+const Map = ({ children }) => {
+ const containerEl = useRef(null);
+
+ const [mapReady, setMapReady] = useState(false);
+
+ useEffect(() => onMapReady(() => setMapReady(true)), []);
+
+ useLayoutEffect(() => {
+ const currentEl = containerEl.current;
+ currentEl.appendChild(element);
+ if (map) {
+ map.resize();
+ }
+ return () => {
+ currentEl.removeChild(element);
+ };
+ }, [containerEl]);
+
+ return (
+ <div style={{ width: '100%', height: '100%' }} ref={containerEl}>
+ {mapReady && children}
+ </div>
+ );
+};
+
+export default Map;