Skip to content

Commit

Permalink
Add typescript and refactor some of map
Browse files Browse the repository at this point in the history
  • Loading branch information
Toby Twigger committed Jun 30, 2023
1 parent 7cb439f commit 2dd6c4e
Show file tree
Hide file tree
Showing 17 changed files with 1,105 additions and 744 deletions.
1,305 changes: 682 additions & 623 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
"pusher-js": "^4.3",
"sass": "~1.32",
"sass-loader": "^12.4.0",
"ts-loader": "^9.4.4",
"typescript": "^5.1.6",
"uuid": "^3.4.0",
"vue": "^2.6.0",
"vue-loader": "^15.9.8",
Expand Down
180 changes: 60 additions & 120 deletions resources/js/ui/components/Route/CRoutePlanner.vue
Original file line number Diff line number Diff line change
@@ -1,37 +1,32 @@
<template>
<div>
<div style="height: 800px" ref="map"></div>
<div id="routing-control">
<c-routing-control :errors="errors" :schema.sync="_schema" :result="result"></c-routing-control>
</div>
<div id="elevation-control">
<c-elevation-control :coordinates="result.coordinates" :selected="selectedIndex" @update:selected="selectedIndex = $event"></c-elevation-control>
</div>
<div id="place-control">
<c-place-control :bounds="bounds" :places.sync="places" :zoom="zoom"></c-place-control>
</div>
<map-canvas ref="map"></map-canvas>
</div>
</template>

<script>
import maplibregl from 'maplibre-gl';
import RoutingControl from './controls/routing/RoutingControl';
import CRoutingControl from './controls/routing/CRoutingControl';
import ElevationControl from './controls/elevation/ElevationControl';
import CElevationControl from './controls/elevation/CElevationControl';
import PlaceControl from './controls/places/PlaceControl';
import CPlaceControl from './controls/places/CPlaceControl';
import CryptoJS from 'crypto-js';
import {cloneDeep} from 'lodash';
import polyline from '@mapbox/polyline';
import units from '../../mixins/units';
import MapCanvas from 'ui/tools/maps/MapCanvas';
import Map from 'ui/tools/maps/map';
import ElevationControl from 'ui/tools/maps/controls/ElevationControl';
import FullscreenControl from 'ui/tools/maps/controls/FullscreenControl';
import RoutingControl from 'ui/tools/maps/controls/RoutingControl';
import PlaceControl from 'ui/tools/maps/controls/PlaceControl';
import GeolocateControl from 'ui/tools/maps/controls/GeolocateControl';
import NavigationControl from 'ui/tools/maps/controls/NavigationControl';
import ScaleControl from 'ui/tools/maps/controls/ScaleControl';
export default {
name: "CRoutePlanner",
components: {CElevationControl, CRoutingControl, CPlaceControl},
components: {MapCanvas},
mixins: [units],
props: {
errors: {
Expand Down Expand Up @@ -67,7 +62,7 @@ export default {
bounds: null,
places: [],
placeMarkers: {},
map: null,
// map: null,
zoom: 1,
geojsonMarker: null,
hoverLngLat: {lng: null, lat: null},
Expand All @@ -78,50 +73,21 @@ export default {
}
},
mounted() {
this.map = new maplibregl.Map({
container: this.$refs.map,
// style: 'https://demotiles.maplibre.org/style.json', // style URL
center: [0, 51], // starting position [lng, lat]
zoom: 1, // starting zoom
style: {
version: 8,
sources: {
osm: {
type: 'raster',
tiles: ['https://a.tile.openstreetmap.org/{z}/{x}/{y}.png'],
tileSize: 256,
attribution: '&copy; OpenStreetMap Contributors',
maxzoom: 19
},
opentopo: {
type: 'raster',
tiles: ['https://a.tile.opentopomap.org/{z}/{x}/{y}.png'],
tileSize: 256,
attribution: 'Map data: &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: &copy; <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>',
maxzoom: 19
},
simple: {
type: 'raster',
tiles: ['https://a.tile.opentopomap.org/{z}/{x}/{y}.png'],
tileSize: 256,
attribution: 'Map data: &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: &copy; <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>',
maxzoom: 19
},
},
layers: [
{
id: 'osm',
type: 'raster',
source: 'osm'
},
],
},
});
this.map.on('load', () => {
this.ready = true;
this.setupMap();
});
this.map = new Map({
container: this.$refs.map.ref,
controls: [
new ElevationControl(),
new FullscreenControl(),
new GeolocateControl(),
new NavigationControl(),
new PlaceControl(),
new RoutingControl(),
new ScaleControl()
.setConfig({
unit: this.$setting.unit_system || 'metric'
})
]
}, {});
},
watch: {
schema: {
Expand Down Expand Up @@ -226,50 +192,6 @@ export default {
},
setupMap: function () {
this.map.addControl(
new maplibregl.NavigationControl({
showZoom: true,
showCompass: true
})
);
// this.map.addControl(
// new maplibregl.ScaleControl({
// maxWidth: 350,
// unit: this.$setting.unit_system || 'metric'
// })
// );
this.map.addControl(
new RoutingControl()
);
this.map.addControl(
new PlaceControl()
);
this.map.addControl(
new ElevationControl()
);
this.map.addControl(
new maplibregl.GeolocateControl({
positionOptions: {
enableHighAccuracy: false,
maximumAge: 0,
timeout: 6000 /* 6 sec */
},
fitBoundsOptions: {
maxZoom: 15
},
trackUserLocation: false,
showAccuracyCircle: true,
showUserLocation: true
})
);
this.map.addControl(new maplibregl.FullscreenControl({}));
this._createGeneralClickHandler();
this.syncMap();
Expand Down Expand Up @@ -319,10 +241,18 @@ export default {
if(waypoint?.id) {
// Check if the marker exists
if(this.markers.hasOwnProperty(waypoint.id)) {
// If it does exist, make sure the location matches.
if(waypoint.location !== this.markers[waypoint.id].getLngLat()) {
// If it does exist, see if we should update it.
let backgroundImage = this._getBackgroundImage(parseInt(waypointIndex) + 1);
let currentBackgroundImage = this.markers[waypoint.id].getElement().style.backgroundImage;
if(currentBackgroundImage === '') {
currentBackgroundImage = null;
}
if(
(waypoint.location !== this.markers[waypoint.id].getLngLat())
|| (currentBackgroundImage !== backgroundImage)
) {
this.markers[waypoint.id].setLngLat([waypoint.location[1], waypoint.location[0]]);
this.markers[waypoint.id].getElement().style.backgroundImage = this._getBackgroundImage(parseInt(waypointIndex) + 1)
this.markers[waypoint.id].getElement().style.backgroundImage = backgroundImage;
}
} else {
// Otherwise create it
Expand Down Expand Up @@ -429,7 +359,10 @@ export default {
markerEl.id = 'waypoint-' + waypoint.id;
markerEl.className = 'marker clickable';
markerEl.style.cursor = 'pointer';
markerEl.style.backgroundImage = this._getBackgroundImage(parseInt(index) + 1);
let backgroundImage = this._getBackgroundImage(parseInt(index) + 1);
if(backgroundImage !== null) {
markerEl.style.backgroundImage = backgroundImage;
}
markerEl.style.width = '20px';
markerEl.style.height = '48px';
Expand Down Expand Up @@ -499,6 +432,9 @@ export default {
_southWest: {lat: bounds._sw.lat, lng: bounds._sw.lng},
};
});
this.map.on('zoomend', function(e) {
self.syncMap();
});
this.map.on('moveend', function(e) {
let bounds = e.target.getBounds();
self.bounds = {
Expand Down Expand Up @@ -573,29 +509,33 @@ export default {
})
},
_getBackgroundImage(text) {
return 'url("data:image/svg+xml,%3C%3Fxml version=\'1.0\' encoding=\'utf-8\'%3F%3E%3Csvg viewBox=\'0 0 500 500\' xmlns=\'http://www.w3.org/2000/svg\' xmlns:bx=\'https://boxy-svg.com\'%3E%3Cellipse style=\'stroke: rgb(0, 0, 0);\' cx=\'253.821\' cy=\'257.697\' rx=\'183.5\' ry=\'183.5\'/%3E%3Ctext style=\'fill: rgb(255, 255, 255); font-family: Arial, sans-serif; font-size: 15.5px; white-space: pre;\' x=\'267.442\' y=\'224.806\' transform=\'matrix(0, 0, 0, 0, 0, 0)\'%3E2%3C/text%3E%3Ctext style=\'fill: rgb(255, 255, 255); font-family: Arial, sans-serif; font-size: ' + (text > 9 ? '2' : '3') + '00px; font-weight: 700; paint-order: fill; stroke-miterlimit: 7; stroke-width: 9px; white-space: pre;\' x=\'171.095\' y=\'363.411\' bx:origin=\'0.49881 0.5\'%3E' + text +'%3C/text%3E%3C/svg%3E")';
let shouldShowWaypoints = this.map.getZoom() > 10;
if(!shouldShowWaypoints) {
return null;
}
return 'url("data:image/svg+xml,%3C%3Fxml version=\'1.0\' encoding=\'utf-8\'%3F%3E%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 500 500\' xmlns:bx=\'https://boxy-svg.com\'%3E%3Cellipse style=\'stroke: rgb(0, 0, 0);\' cx=\'253.821\' cy=\'257.697\' rx=\'183.5\' ry=\'183.5\'/%3E%3Ctext style=\'fill: rgb(255, 255, 255); font-family: Arial, sans-serif; font-size: 15.5px; white-space: pre;\' x=\'267.442\' y=\'224.806\' transform=\'matrix(0, 0, 0, 0, 0, 0)\'%3E2%3C/text%3E%3Ctext style=\'fill: rgb(255, 255, 255); font-family: Arial, sans-serif; font-size: ' + (text > 9 ? '2' : '3') + '00px; font-weight: 700; paint-order: fill; stroke-miterlimit: 7; stroke-width: 9px; white-space: pre;\' x=\'171.095\' y=\'363.411\' bx:origin=\'0.49881 0.5\'%3E' + text +'%3C/text%3E%3C/svg%3E")';
},
_getPlaceBackgroundImage(type) {
if(type === 'food_drink') {
return 'url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 24 24\'%3E%3Ctitle%3Efood-fork-drink%3C/title%3E%3Cpath d=\'M3,3A1,1 0 0,0 2,4V8L2,9.5C2,11.19 3.03,12.63 4.5,13.22V19.5A1.5,1.5 0 0,0 6,21A1.5,1.5 0 0,0 7.5,19.5V13.22C8.97,12.63 10,11.19 10,9.5V8L10,4A1,1 0 0,0 9,3A1,1 0 0,0 8,4V8A0.5,0.5 0 0,1 7.5,8.5A0.5,0.5 0 0,1 7,8V4A1,1 0 0,0 6,3A1,1 0 0,0 5,4V8A0.5,0.5 0 0,1 4.5,8.5A0.5,0.5 0 0,1 4,8V4A1,1 0 0,0 3,3M19.88,3C19.75,3 19.62,3.09 19.5,3.16L16,5.25V9H12V11H13L14,21H20L21,11H22V9H18V6.34L20.5,4.84C21,4.56 21.13,4 20.84,3.5C20.63,3.14 20.26,2.95 19.88,3Z\' /%3E%3C/svg%3E")';
return 'url("/dist/images/map/food_drink.svg")';
}
if(type === 'shops') {
return 'url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 24 24\'%3E%3Ctitle%3Ebasket%3C/title%3E%3Cpath d=\'M5.5,21C4.72,21 4.04,20.55 3.71,19.9V19.9L1.1,10.44L1,10A1,1 0 0,1 2,9H6.58L11.18,2.43C11.36,2.17 11.66,2 12,2C12.34,2 12.65,2.17 12.83,2.44L17.42,9H22A1,1 0 0,1 23,10L22.96,10.29L20.29,19.9C19.96,20.55 19.28,21 18.5,21H5.5M12,4.74L9,9H15L12,4.74M12,13A2,2 0 0,0 10,15A2,2 0 0,0 12,17A2,2 0 0,0 14,15A2,2 0 0,0 12,13Z\' /%3E%3C/svg%3E")';
return 'url("/dist/images/map/basket.svg")';
}
if(type === 'tourist') {
return 'url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 24 24\'%3E%3Ctitle%3Eeiffel-tower%3C/title%3E%3Cpath d=\'M8.21 17C8.65 16.15 9.06 15.16 9.44 14H9V12H10C10.61 9.4 11 6.13 11 2H13C13 6.13 13.4 9.4 14 12H15V14H14.56C14.94 15.16 15.35 16.15 15.79 17H17L17 19L19 22H16.58C15.81 20.24 14.05 19 12 19C9.95 19 8.19 20.24 7.42 22H5L7 19L6.97 17H8.21M12.59 14H11.41C11.07 15.13 10.69 16.13 10.28 17H13.72C13.32 16.13 12.93 15.13 12.59 14Z\' /%3E%3C/svg%3E")';
return 'url("/dist/images/map/eiffel-tower.svg")';
}
if(type === 'accommodation') {
return 'url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 24 24\'%3E%3Ctitle%3Ebed%3C/title%3E%3Cpath d=\'M19,7H11V14H3V5H1V20H3V17H21V20H23V11A4,4 0 0,0 19,7M7,13A3,3 0 0,0 10,10A3,3 0 0,0 7,7A3,3 0 0,0 4,10A3,3 0 0,0 7,13Z\' /%3E%3C/svg%3E")';
return 'url("/dist/images/map/accommodation.svg")';
}
if(type === 'water') {
return 'url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 24 24\'%3E%3Ctitle%3Ewater%3C/title%3E%3Cpath d=\'M12,20A6,6 0 0,1 6,14C6,10 12,3.25 12,3.25C12,3.25 18,10 18,14A6,6 0 0,1 12,20Z\' /%3E%3C/svg%3E")';
return 'url("/dist/images/map/water.svg")';
}
if(type === 'toilets') {
return 'url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 24 24\'%3E%3Ctitle%3Etoilet%3C/title%3E%3Cpath d=\'M9,22H17V19.5C19.41,17.87 21,15.12 21,12V4A2,2 0 0,0 19,2H15C13.89,2 13,2.9 13,4V12H3C3,15.09 5,18 9,19.5V22M5.29,14H18.71C18.14,15.91 16.77,17.5 15,18.33V20H11V18.33C9,18 5.86,15.91 5.29,14M15,4H19V12H15V4M16,5V8H18V5H16Z\' /%3E%3C/svg%3E")';
return 'url("/dist/images/map/toilets.svg")';
}
if(type === 'other') {
return 'url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 24 24\'%3E%3Ctitle%3Ecrosshairs-question%3C/title%3E%3Cpath d=\'M3.05 13H1V11H3.05C3.5 6.83 6.83 3.5 11 3.05V1H13V3.05C17.17 3.5 20.5 6.83 20.95 11H23V13H20.95C20.5 17.17 17.17 20.5 13 20.95V23H11V20.95C6.83 20.5 3.5 17.17 3.05 13M12 5C8.13 5 5 8.13 5 12S8.13 19 12 19 19 15.87 19 12 15.87 5 12 5M11.13 17.25H12.88V15.5H11.13V17.25M12 6.75C10.07 6.75 8.5 8.32 8.5 10.25H10.25C10.25 9.28 11.03 8.5 12 8.5S13.75 9.28 13.75 10.25C13.75 12 11.13 11.78 11.13 14.63H12.88C12.88 12.66 15.5 12.44 15.5 10.25C15.5 8.32 13.93 6.75 12 6.75Z\' /%3E%3C/svg%3E%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 24 24\'%3E%3Ctitle%3Ecrosshairs-question%3C/title%3E%3Cpath d=\'M3.05 13H1V11H3.05C3.5 6.83 6.83 3.5 11 3.05V1H13V3.05C17.17 3.5 20.5 6.83 20.95 11H23V13H20.95C20.5 17.17 17.17 20.5 13 20.95V23H11V20.95C6.83 20.5 3.5 17.17 3.05 13M12 5C8.13 5 5 8.13 5 12S8.13 19 12 19 19 15.87 19 12 15.87 5 12 5M11.13 17.25H12.88V15.5H11.13V17.25M12 6.75C10.07 6.75 8.5 8.32 8.5 10.25H10.25C10.25 9.28 11.03 8.5 12 8.5S13.75 9.28 13.75 10.25C13.75 12 11.13 11.78 11.13 14.63H12.88C12.88 12.66 15.5 12.44 15.5 10.25C15.5 8.32 13.93 6.75 12 6.75Z\' /%3E%3C/svg%3E")';
return 'url("/dist/images/map/help.svg")';
}
return null;
}
Expand Down
36 changes: 36 additions & 0 deletions resources/js/ui/tools/maps/MapCanvas.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<template>
<div>
<div style="height: 800px" ref="map"></div>
<!-- <div id="routing-control">-->
<!-- <c-routing-control :errors="errors" :schema.sync="_schema" :result="result"></c-routing-control>-->
<!-- </div>-->
<!-- <div id="elevation-control">-->
<!-- <c-elevation-control :coordinates="result.coordinates" :selected="selectedIndex" @update:selected="selectedIndex = $event"></c-elevation-control>-->
<!-- </div>-->
<!-- <div id="place-control">-->
<!-- <c-place-control :bounds="bounds" :places.sync="places" :zoom="zoom"></c-place-control>-->
<!-- </div>-->
</div>
</template>

<script>
import CRoutingControl from 'ui/components/Route/controls/routing/CRoutingControl';
import CElevationControl from 'ui/components/Route/controls/elevation/CElevationControl';
import CPlaceControl from 'ui/components/Route/controls/places/CPlaceControl';
import maplibregl from 'maplibre-gl';
import Map from 'ui/tools/maps/map';
export default {
name: "MapCanvas",
components: {CPlaceControl, CElevationControl, CRoutingControl},
computed: {
ref() {
return this.$ref.map;
}
},
}
</script>

<style scoped>
</style>
18 changes: 18 additions & 0 deletions resources/js/ui/tools/maps/controls/ElevationControl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {Control} from "../types/MapType";
import BaseElevationControl from './../../../components/Route/controls/elevation/ElevationControl.js';
import {IControl} from "maplibre-gl";

class ElevationControl implements Control {
config: object = {};

setConfig(config: object = {}): this {
this.config = config;
return this;
};

createControl(): IControl {
return new BaseElevationControl({});
}
}

export default ElevationControl;
18 changes: 18 additions & 0 deletions resources/js/ui/tools/maps/controls/FullscreenControl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {Control} from "../types/MapType";
import maplibregl, {IControl} from "maplibre-gl";

class FullscreenControl implements Control {
config: object = {};

setConfig(config: object = {}): this {
this.config = config;

return this;
};

createControl(): IControl {
return new maplibregl.FullscreenControl({});
}
}

export default FullscreenControl;
31 changes: 31 additions & 0 deletions resources/js/ui/tools/maps/controls/GeolocateControl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {Control} from "../types/MapType";
import maplibregl, {IControl} from "maplibre-gl";

class GeolocateControl implements Control {
config: object = {};

setConfig(config: object = {}): this {
this.config = config;

return this;
};

createControl(): IControl {
return new maplibregl.GeolocateControl({
positionOptions: {
enableHighAccuracy: false,
maximumAge: 0,
timeout: 6000 /* 6 sec */
},
fitBoundsOptions: {
maxZoom: 15
},
trackUserLocation: false,
showAccuracyCircle: true,
showUserLocation: true
});
};

}

export default GeolocateControl;
Loading

0 comments on commit 2dd6c4e

Please sign in to comment.