136 lines
4.6 KiB
JavaScript
136 lines
4.6 KiB
JavaScript
//mapbox-utils.js
|
|
import mapboxgl from 'mapbox-gl/dist/mapbox-gl.js';
|
|
import parseLocation from './parse-location';
|
|
import selectPlaceInForm from './select-place';
|
|
|
|
mapboxgl.accessToken = 'pk.eyJ1Ijoiam9ubnliYXJuZXMiLCJhIjoiY2l2cDhjYW04MDAwcjJ0cG1uZnhqcm82ayJ9.qA2zeVA-nsoMh9IFrd5KQw';
|
|
|
|
//define some functions to be used in the default function.
|
|
const titlecase = (string) => {
|
|
return string.split('-').map(([first,...rest]) => first.toUpperCase() + rest.join('').toLowerCase()).join(' ')
|
|
};
|
|
|
|
const addMapTypeOption = (map, menu, option, checked = false) => {
|
|
let input = document.createElement('input');
|
|
input.setAttribute('id', option);
|
|
input.setAttribute('type', 'radio');
|
|
input.setAttribute('name', 'toggle');
|
|
input.setAttribute('value', option);
|
|
if (checked == true) {
|
|
input.setAttribute('checked', 'checked');
|
|
}
|
|
input.addEventListener('click', function () {
|
|
map.setStyle('mapbox://styles/mapbox/' + option + '-v9');
|
|
});
|
|
let label = document.createElement('label');
|
|
label.setAttribute('for', option);
|
|
label.appendChild(document.createTextNode(titlecase(option)));
|
|
menu.appendChild(input);
|
|
menu.appendChild(label);
|
|
}
|
|
|
|
const makeMapMenu = (map) => {
|
|
let mapMenu = document.createElement('div');
|
|
mapMenu.classList.add('map-menu');
|
|
addMapTypeOption(map, mapMenu, 'streets', true);
|
|
addMapTypeOption(map, mapMenu, 'satellite-streets');
|
|
return mapMenu;
|
|
}
|
|
|
|
//the main function
|
|
export default function addMap(div, position = null, places = null) {
|
|
let dataLatitude = div.dataset.latitude;
|
|
let dataLongitude = div.dataset.longitude;
|
|
let dataId = div.dataset.id;
|
|
let data = window['geojson'+dataId];
|
|
if (data == null) {
|
|
data = {
|
|
"type": "FeatureCollection",
|
|
"features": [{
|
|
"type": "Feature",
|
|
"geometry": {
|
|
"type": "Point",
|
|
"coordinates": [dataLongitude, dataLatitude]
|
|
},
|
|
"properties": {
|
|
"title": "Current Location",
|
|
"icon": "circle-stroked",
|
|
"uri": "current-location"
|
|
}
|
|
}]
|
|
};
|
|
}
|
|
if (places != null) {
|
|
for (let place of places) {
|
|
let placeLongitude = parseLocation(place.location).longitude;
|
|
let placeLatitude = parseLocation(place.location).latitude;
|
|
data.features.push({
|
|
"type": "Feature",
|
|
"geometry": {
|
|
"type": "Point",
|
|
"coordinates": [placeLongitude, placeLatitude]
|
|
},
|
|
"properties": {
|
|
"title": place.name,
|
|
"icon": "circle",
|
|
"uri": place.slug
|
|
}
|
|
});
|
|
}
|
|
}
|
|
if (position != null) {
|
|
let dataLongitude = position.coords.longitude;
|
|
let dataLatitude = position.coords.latitude;
|
|
}
|
|
let map = new mapboxgl.Map({
|
|
container: div,
|
|
style: 'mapbox://styles/mapbox/streets-v9',
|
|
center: [dataLongitude, dataLatitude],
|
|
zoom: 15
|
|
});
|
|
if (position == null) {
|
|
map.scrollZoom.disable();
|
|
}
|
|
map.addControl(new mapboxgl.NavigationControl());
|
|
div.appendChild(makeMapMenu(map));
|
|
map.on('load', function () {
|
|
map.addSource('points', {
|
|
"type": "geojson",
|
|
"data": data
|
|
});
|
|
map.addLayer({
|
|
"id": "points",
|
|
"interactive": true,
|
|
"type": "symbol",
|
|
"source": "points",
|
|
"layout": {
|
|
"icon-image": "{icon}-15",
|
|
"text-field": "{title}",
|
|
"text-offset": [0, 1]
|
|
}
|
|
});
|
|
});
|
|
if (position != null) {
|
|
map.on('click', function (e) {
|
|
let features = map.queryRenderedFeatures(e.point, {
|
|
layer: ['points']
|
|
});
|
|
// if there are features within the given radius of the click event,
|
|
// fly to the location of the click event
|
|
if (features.length) {
|
|
// Get coordinates from the symbol and center the map on those coordinates
|
|
map.flyTo({center: features[0].geometry.coordinates});
|
|
selectPlaceInForm(features[0].properties.uri);
|
|
}
|
|
});
|
|
}
|
|
if (data.features && data.features.length > 1) {
|
|
let bounds = new mapboxgl.LngLatBounds();
|
|
for (let feature of data.features) {
|
|
bounds.extend(feature.geometry.coordinates);
|
|
}
|
|
map.fitBounds(bounds, { padding: 65});
|
|
}
|
|
|
|
return map;
|
|
}
|