var map;
var map_styles;
var map_overlay;
var map_interaction;
var map_feature_array;
var map_default_zoomlevel;
var map_txt_start;
var map_txt_direction;
var map_marker;
var map_dash_spacer;
var $map_popup;
//=== initialize the map ===========================================================================
function initMap(mapid) {
setMapStyles();
//mapid cannot be null
if (mapid == null) {
mapid = '';
}
//check if the map exists
var $htmlmap = $('#map' + mapid);
if ($htmlmap.length === 0) {
return;
}
//declare some variables
map_default_zoomlevel = 7;
map_txt_start = 'Start';
map_txt_direction = 'Direction';
map_dash_spacer = ' - ';
$map_popup = $('#map-popup' + mapid);
var map_zoomlevel = map_default_zoomlevel;
var map_mapcenter = cmsScriptVariables.dutch_map_center;
var controls = [new ol.control.Zoom()];
var tooltips = true;
//check for data attribute values
if ($htmlmap.data('zoom') === false) {
controls = [];
}
if ($htmlmap.data('nott') === true) {
tooltips = false;
}
if ($htmlmap.data('center') != null) {
map_mapcenter = $htmlmap.data('center');
}
if ($htmlmap.data('zoomlevel') != null) {
map_zoomlevel = parseInt($htmlmap.data('zoomlevel'));
}
//create the map object
map = new ol.Map({
target: 'map' + mapid,
layers: [
new ol.layer.Tile({
source: new ol.source.OSM(),
name: 'baselayer'
})
],
view: new ol.View({
center: ol.proj.fromLonLat(map_mapcenter),
zoom: map_zoomlevel,
maxZoom: 18,
constrainResolution: true
}),
controls: controls,
interactions: ol.interaction.defaults({
mouseWheelZoom: false
})
});
//set the opacity of the tooltip to normal (otherwise it is visible before map init)
$('.ol-popup').css('opacity', '1');
//create an overlay to anchor the hover popup to the map
if (tooltips) {
addMapTooltips();
}
//bind keyboard to control the map if there is only one
if ($('.ol-map-container').length === 1) {
addMapKeyboardControls();
}
//svg images in zoom buttons
$('.ol-zoom-in').html(getSvgIcon('plus'));
$('.ol-zoom-out').html(getSvgIcon('minus'));
//add the context menu
createContextMenu();
//if you want to enable zoom with scroll wheel and/or remove zoom controls from the map, use:
//map = new ol.Map({
// controls: [],
// interactions: ol.interaction.defaults({ mouseWheelZoom: true })
//});
//add a custom style layer to the map
//olms.apply(map, 'https://api.maptiler.com/maps/basic/style.json?key=xxxxx');
}
//=== set the map styles for gpx tracks ============================================================
function setMapStyles() {
//available colors: black, blue, green, grey, magenta, orange, purple, red, white, yellow
map_styles = {
'track-black': new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#000000',
width: 3
}),
}),
'track-blue': new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#0f75bc',
width: 3
}),
}),
'track-green': new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#308c07',
width: 3
}),
}),
'track-grey': new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#999999',
width: 3
}),
}),
'track-magenta': new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#c5007e',
width: 3
}),
}),
'track-orange': new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#f49b00',
width: 3
}),
}),
'track-purple': new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#566895',
width: 3
}),
}),
'track-red': new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#bf1616',
width: 3
}),
}),
'track-white': new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#ffffff',
width: 3
}),
}),
'track-yellow': new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#f4e600',
width: 3
}),
}),
};
}
//=== create an overlay to anchor the hover popup to the map =======================================
function addMapTooltips() {
//create a mew overlay
map_overlay = new ol.Overlay({
element: document.getElementById($map_popup.prop('id')),
autoPan: {
animation: {
duration: 250,
}
}
});
//add the overlay to the map
map.addOverlay(map_overlay);
//add a mousemove function to the map to detect a marker and if found show popup
map.on('pointermove', function (e) {
var feature = map.forEachFeatureAtPixel(e.pixel, function (feat, layer) {
return feat;
});
//get the current position of the mouse in pixels relative to the map div container
//console.log(e.pixel)
//show the marker info if there is a name property and it has contents
if (feature && typeof feature.get('name') != 'undefined' && feature.get('name') != null && feature.get('name') !== '') {
$map_popup.html(feature.get('name'));
map_overlay.setPosition(e.coordinate);
} else {
map_overlay.setPosition(null);
}
});
}
//=== bind keyboard to control the map =============================================================
function addMapKeyboardControls() {
document.body.onkeydown = function (e) {
//minzoom = 3, maxzoom = 18
var factor = 80;
var increment = 5;
var minzoom = 3;
var view = map.getView();
var center = view.getCenter();
var zoomlevel = view.getZoom();
var step = view.getResolution() * (factor + (zoomlevel - minzoom) * increment);
try {
switch (e.key) {
//left
case 'ArrowLeft':
setMapCenter([center[0] - step, center[1]], 250);
break;
//up
case 'ArrowUp':
e.preventDefault();
setMapCenter([center[0], center[1] + step], 250);
break;
//right
case 'ArrowRight':
setMapCenter([center[0] + step, center[1]], 250);
break;
//down
case 'ArrowDown':
e.preventDefault();
setMapCenter([center[0], center[1] - step], 250);
break;
//zoom in
case '+':
case '=':
setMapZoom(map.getView().getZoom() + 1);
break;
//zoom out
case '-':
setMapZoom(map.getView().getZoom() - 1);
break;
}
} catch (e) {
}
};
}
//=== add a marker to the map ======================================================================
function addMarker(id, name, color, lat, lng, draggable, custom_marker, custom_layer) {
//create a feature
var feature = new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([lng, lat])),
name: name,
id: id,
color: color,
type: 'marker'
});
var markerimg = `/images/marker-${color}.png`;
if (custom_marker != null && custom_marker !== '') {
markerimg = custom_marker;
}
//create an icon style with an image as marker
var style = new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 36],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: markerimg
}))
});
//or create an icon style with a shape as marker
//var style = new ol.style.Style({
// image: new ol.style.Circle({
// radius: 10,
// stroke: new ol.style.Stroke({
// color: 'black',
// width: 3
// }),
// fill: new ol.style.Fill({
// color: 'white'
// }),
// })
//});
//add the style to the feature
feature.setStyle(style);
//create a layer and add the feature
var layer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [feature]
}),
name: name,
type: 'marker',
zIndex: 100
});
//is there a custom layer
if (custom_layer != null) {
custom_layer.getSource().addFeature(feature);
layer = custom_layer;
} else {
//add the layer to the map
map.addLayer(layer);
}
//no draggable marker
if (!draggable) {
return;
}
//add a modifier
var modify = new ol.interaction.Modify({
hitDetection: layer,
source: layer.getSource()
});
//needed variables
var container = document.getElementById('map-container');
var overlay = modify.getOverlay().getSource();
var $cmslat = $('.cms_lat');
var $cmslng = $('.cms_lng');
//the container does not have the required id
if (container == null) {
alert('The map container "<div class="ol-map-container">" does not have the id "map-container" required for draggable markers.');
return;
}
//modify handlers
modify.on(['modifystart', 'modifyend'], function (e) {
container.style.cursor = e.type === 'modifystart' ? 'grabbing' : 'pointer';
});
overlay.on(['addfeature', 'removefeature'], function (e) {
container.style.cursor = e.type === 'addfeature' ? 'pointer' : '';
});
//get the coordinates during drag
feature.on('change', function () {
var newcoords = ol.proj.toLonLat(this.getGeometry().getCoordinates());
//console.log(ol.proj.toLonLat(this.getGeometry().getCoordinates()));
$cmslat.val(newcoords[1]);
$cmslng.val(newcoords[0]);
$cmslat.html(newcoords[1]);
$cmslng.html(newcoords[0]);
$cmslat.show();
$cmslng.show();
$cmslat.closest('div').show();
}, feature);
//add the modifier to the map
map.addInteraction(modify);
//if it is the first marker make it a global variable
if (map_marker == null) {
map_marker = feature;
}
}
//=== load a gpx file from an url ==================================================================
function addGpxFromUrl(url, name, color, show_marker) {
//create a layer
var layer = new ol.layer.Vector({
source: new ol.source.Vector({
url: url,
format: new ol.format.GPX()
}),
style: function () {
return map_styles['track-' + color];
},
name: name,
type: 'track',
zIndex: 100
});
//add the layer to the map
map.addLayer(layer);
//bind a listeret to the layer (needed becaue loading the source from an url is async)
layer.getSource().on('addfeature', function (e) {
//get the coordinates from the layer
var coords = e.feature.getGeometry().clone().transform('EPSG:3857', 'EPSG:4326');
//put the coordinates in a html element (to use elsewhere or post it to the server)
var json = saveGpxToHtmlElement(e.feature);
//add a marker to the first coordinate
if (show_marker) {
addMarker(1, name + map_dash_spacer + map_txt_start, color, coords.getFirstCoordinate()[1], coords.getFirstCoordinate()[0], false);
}
//zoom and fit bounds
zoomAndFitBounds(layer);
});
}
//=== load a gpx file from a string variable =======================================================
function addGpxFromString(gpx, name, color, show_marker, animate) {
//remove the existing layer
removeLayerFromMap(name);
//create a layer
var layer = new ol.layer.Vector({
source: new ol.source.Vector({}),
style: function () {
return map_styles['track-' + color];
},
name: name,
type: 'track',
zIndex: 100
});
//read the features from the gpx
var features = new ol.format.GPX().readFeatures(gpx, {
dataProjection: 'EPSG:4326',
featureProjection: 'EPSG:3857'
});
//add the features to the layer
layer.getSource().addFeatures(features);
//add the layer to the map
map.addLayer(layer);
//get the coordinates from the layer
var coords = features[0].getGeometry().clone().transform('EPSG:3857', 'EPSG:4326');
//put the coordinates in a html element (to use elsewhere or post it to the server)
var json = saveGpxToHtmlElement(features);
//to get the distance in km
var distance = ol.sphere.getLength(layer.getSource().getFeatures()[0].getGeometry()) / 1000;
//add a marker to the first coordinate
if (show_marker) {
addMarker(1, name + map_dash_spacer + map_txt_start + map_dash_spacer + distance.toFixed(1) + ' km', color, coords.getFirstCoordinate()[1], coords.getFirstCoordinate()[0], false);
}
//zoom and fit bounds
zoomAndFitBounds(layer);
//add a line animation
if (animate) {
animateLine(new ol.geom.LineString(json).transform('EPSG:4326', 'EPSG:3857'), name + map_dash_spacer + map_txt_direction);
}
}
//=== add a gpx track from an array of single points [[52.8058, 6.7958], [52.8056, 6.7957], ... ] ==
function addGpxFromPoints(gpx, name, color, show_marker, animate) {
if (gpx.length === 0) {
return;
}
//openlayers uses [lon, lat], not [lat, lon]
if (gpx[0][0] > 20 && gpx[0][1] < 20) {
gpx.map(function (l) {
return l.reverse();
});
}
//create a geometry from the coordinates
var geometry = new ol.geom.LineString(gpx).transform('EPSG:4326', 'EPSG:3857');
//create a layer
var layer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [
new ol.Feature({
geometry: geometry,
name: name
})
]
}),
style: function () {
return map_styles['track-' + color];
},
name: name,
type: 'track',
zIndex: 100
});
//add the layer to the map
map.addLayer(layer);
//add a marker to the first coordinate
if (show_marker) {
addMarker(2, name + map_dash_spacer + map_txt_start, color, gpx[0][1], gpx[0][0], false);
}
//zoom and fit bounds
zoomAndFitBounds(layer);
//add a line animation
if (animate) {
animateLine(geometry, name + map_dash_spacer + map_txt_direction);
}
}
//=== enable dragging and dropping a gpx track on the map ==========================================
function addGpxFromDragDrop() {
//if an interaction exists remove it first
if (map_interaction) {
map.removeInteraction(map_interaction);
}
//create the interaction
map_interaction = new ol.interaction.DragAndDrop({
formatConstructors: [
ol.format.GPX
],
});
//on drag event
map_interaction.on('addfeatures', function (e) {
//reset the map
resetMap();
//create a layer
var layer = new ol.layer.Vector({
source: new ol.source.Vector({
features: e.features,
}),
style: function () {
return map_styles['track-red'];
},
name: 'GpxFromDragDrop',
type: 'track',
zIndex: 100
});
//add the layer to the map
map.addLayer(layer);
//get the coordinates from the layer
var coords = e.features[0].getGeometry().clone().transform('EPSG:3857', 'EPSG:4326');
//put the coordinates in a html element (to use elsewhere or post it to the server)
var json = saveGpxToHtmlElement(e.features);
//add a marker to the first coordinate
addMarker(1, map_txt_start, 'blue', coords.getFirstCoordinate()[1], coords.getFirstCoordinate()[0], false);
//zoom and fit bounds
zoomAndFitBounds(layer);
});
//add the interaction to the map
map.addInteraction(map_interaction);
}
//=== add a gpx with a html file upload control ====================================================
function addGpxFromFileUpload() {
var color = 'red';
var show_marker = false;
var animate = true;
//bind a change event to the control
$('#map-upload').on('change', function () {
var $this = $(this);
var gpxfile = document.getElementById($this.prop('id')).files[0];
//reset the map
resetMap();
//create a reader
var reader = new FileReader();
reader.onload = function (e) {
//if there a color defined
if ($this.data('color') != null) {
color = $this.data('color');
}
//start marker to be shown
if ($this.data('marker') != null) {
show_marker = $this.data('marker');
}
//should the line be animated
if ($this.data('animate') != null) {
animate = $this.data('animate');
}
//add it to the map
addGpxFromString(e.target.result, 'GpxFromFileUpload', color, show_marker, animate);
};
reader.readAsText(gpxfile);
$this.val('');
});
}
//=== add multiple markers from an array ===========================================================
function addMultipleMarkers(markerArr, type) {
var markerimg = `/images/site/marker-${type}.png`;
var markerimg_hover = `/images/site/marker-${type}-red.png`;
var url = '/toertochten/';
if (type === 'club') {
url = '/clubs/';
} else if (type == 'track') {
url = '/routes/';
}
var normalstyle = new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 0.5],
src: markerimg
})),
zIndex: 100
});
var hoverstyle = new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 0.5],
src: markerimg_hover
})),
zIndex: 1000
});
//create a new layer
var layer = new ol.layer.Vector({
source: new ol.source.Vector(),
style: normalstyle
});
//loop all the markers to add popover
for (var i = 0; i < markerArr.length; i++) {
var item = markerArr[i];
layer.getSource().addFeature(
new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([parseFloat(item.lng), parseFloat(item.lat)])),
id: item.id,
type: 'icon',
name: `<strong>${item.naam}</strong><br>${item.regel2}`
})
);
}
map_feature_array = layer.getSource().getFeatures();
//make the marker red on hover
var hover = null;
map.on('pointermove', function (evt) {
map.getTargetElement().style.cursor = map.hasFeatureAtPixel(evt.pixel) ? 'pointer' : '';
if (hover != null) {
hover.setStyle(normalstyle);
hover = null;
}
map.forEachFeatureAtPixel(evt.pixel, function (f) {
if (f.get('type') === 'icon') {
hover = f;
return true;
} else {
return false;
}
});
if (hover) {
hover.setStyle(hoverstyle);
}
});
//add the layer to the map
map.addLayer(layer);
//make the marker clickable
map.on('click', (e) => {
map.forEachFeatureAtPixel(e.pixel, function (f) {
if (f.get('type') === 'icon') {
location.href = url + hover.get('id');
return true;
} else {
return false;
}
});
});
//zoom and fit bounds
//zoomAndFitBounds(layer);
}
//=== move the map marker to a new position ========================================================
function moveMarker(lat, lng) {
var coordinates = ol.proj.fromLonLat([lng, lat]);
map_marker.getGeometry().setCoordinates(coordinates);
}
//=== add a click event to the map to get the clicked coordinate ===================================
function addClickEvent() {
var $popupclick = $('#map-popup-click');
//check if the click element exists
if ($popupclick.length === 0) {
alert('The element "<div id="map-popup-click" class="ol-popup"></div>" was not found.')
return;
}
//create an overlay to anchor the hover popup to the map
var clickOverlay = new ol.Overlay({
element: document.getElementById($popupclick.prop('id')),
autoPan: {
animation: {
duration: 250,
}
}
});
//add the overlay to the map
map.addOverlay(clickOverlay);
//add the click event and show the popup
map.on('singleclick', function (e) {
//if a popup is open then close it on map click
if (clickOverlay.getPosition()) {
clickOverlay.setPosition(null);
} else {
var location = ol.proj.toLonLat(e.coordinate).toString().split(',');
$popupclick.html(`<p>You clicked here:</p><code>${location[1]}<br>${location[0]}</code>`);
clickOverlay.setPosition(e.coordinate);
}
});
}
//=== add a moving marker to a route ===============================================================
function animateLine(route, name) {
var speed = 30;
var distance = 0;
var lasttime;
var position = new ol.geom.Point(route.clone().getFirstCoordinate());
var feature = new ol.Feature({
geometry: position,
});
var startMarker = new ol.Feature({
geometry: position,
});
var endMarker = new ol.Feature({
geometry: position
});
//create an icon style with a shape as marker
var style = new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
stroke: new ol.style.Stroke({
color: 'black',
width: 2
}),
fill: new ol.style.Fill({
color: 'red'
})
})
});
//create a layer with the marker that will move
var layer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [feature, startMarker, endMarker],
}),
name: name,
zIndex: 200
});
//add the layer to the map
map.addLayer(layer);
//function to move the marker
function moveFeature(e) {
var time = e.frameState.time;
distance = (distance + (speed * (time - lasttime)) / 1e6) % 2;
lasttime = time;
//if the distance > 1 then the end has been reached so restart
if (distance > 1) {
stopAnimation();
startAnimation();
}
//set the new coordinate for the marker
position.setCoordinates(route.getCoordinateAt(distance));
//draw it on the map
var context = ol.render.getVectorContext(e);
context.setStyle(style);
context.drawGeometry(position);
map.render();
}
//start the animation
function startAnimation() {
distance = 0;
lasttime = Date.now();
layer.on('postrender', moveFeature);
feature.setGeometry(null);
}
//stop the animation
function stopAnimation() {
feature.setGeometry(position);
layer.un('postrender', moveFeature);
}
//start
startAnimation();
}
//=== add multiple markers from an array and make them clustered ===================================
function addMultipleMarkersClustered(markerArr) {
if (markerArr.length === 0) {
return;
}
var url = '';
//sort the array
markerArr.sort((a, b) => a.lat - b.lat);
//create the features
map_feature_array = new Array(markerArr.length);
var prevmarker;
var offsetdefault = 0.0015;
var offsettotal = offsetdefault;
//loop the markers
for (let i = 0; i < markerArr.length; ++i) {
var item = markerArr[i];
var point = new ol.geom.Point(ol.proj.fromLonLat([parseFloat(item.lng), parseFloat(item.lat)]));
var markercompare = item.lng.toFixed(3) + '_' + item.lat.toFixed(3);
//if the features have the same coordinates move them slightly so they appear next to each other
if (markercompare === prevmarker) {
point = new ol.geom.Point(ol.proj.fromLonLat([parseFloat(item.lng) + offsettotal, parseFloat(item.lat)]));
offsettotal += offsetdefault;
} else {
offsettotal = offsetdefault;
}
map_feature_array[i] = new ol.Feature({
geometry: point,
id: item.id,
type: 'icon',
name: `<strong>${item.naam}</strong><br>${item.regel2}`
});
prevmarker = markercompare;
}
//create the source
var clusterSource = new ol.source.Cluster({
distance: 40,
minDistance: 10,
source: new ol.source.Vector({
features: map_feature_array,
})
});
//clustered style
var zindex = 100;
var clusters = new ol.layer.Vector({
zIndex: 1,
source: clusterSource,
style: function (feature) {
const size = feature.get('features').length;
//if there are no more clusters you can return a different icon
if (size === 1) {
//var style = new ol.style.Style();
//return style;
}
var radius = 12;
var textsize = 1;
var text = size.toString();
//dynamic cluster marker size calculations
if (size > 100) {
radius = (size * 0.2);
textsize = size / 60;
} else if (size > 50) {
radius = (size * 0.4);
textsize = size / 25;
} else if (size > 25) {
radius = (size * 0.6);
textsize = size / 20;
} else if (size > 1) {
radius = 15;
textsize = 1.3;
}
//max markercluster size
if (radius > 75) {
radius = 75;
textsize = 5;
}
var style = new ol.style.Style({
image: new ol.style.Circle({
radius: radius,
fill: new ol.style.Fill({
color: 'black'
}),
stroke: new ol.style.Stroke({
color: 'white',
width: 1
}),
}),
text: new ol.style.Text({
text: text,
fill: new ol.style.Fill({
color: '#fff',
}),
scale: textsize,
offsetY: size > 50 ? 2 : 1
}),
zIndex: zindex
});
zindex++;
return style;
},
});
//create a tile layer
var raster = new ol.layer.Tile({
source: new ol.source.OSM()
});
//add the layers to the map
map.addLayer(raster);
map.addLayer(clusters);
//make the marker clickable
map.on('click', (e) => {
clusters.getFeatures(e.pixel).then((clickedFeatures) => {
if (clickedFeatures.length) {
//get the clustered coordinates
const features = clickedFeatures[0].get('features');
//when there are multiple features do a zoom otherwise handle the click
if (features.length > 1) {
const extent = ol.extent.boundingExtent(
features.map((r) => r.getGeometry().getCoordinates())
);
map.getView().fit(extent, { duration: 1000, padding: [50, 50, 50, 50] });
} else {
location.href = url + features[0].get('id');
}
}
});
});
//show a mouse pointer and popup on hover
map.on('pointermove', function (e) {
map.getTargetElement().style.cursor = map.hasFeatureAtPixel(e.pixel) ? 'pointer' : '';
clusters.getFeatures(e.pixel).then((hoveredFeatures) => {
if (hoveredFeatures.length) {
//get the clustered coordinates
const features = hoveredFeatures[0].get('features');
//when there is a single features show the popup
if (features.length === 1) {
if (features[0] && typeof features[0].get('name') != 'undefined' && features[0].get('name') != null && features[0].get('name') !== '') {
$map_popup.html(features[0].get('name'));
map_overlay.setPosition(e.coordinate);
} else {
map_overlay.setPosition(null);
}
}
}
});
});
//zoom and fit bounds
zoomAndFitBounds(clusterSource);
}
//=== put the coordinates in a html element (to use elsewhere or post it to the server) ============
function saveGpxToHtmlElement(features) {
//get the coordinates from the layer
var json = '';
for (var i = 0; i < features.length; i++) {
var coords = features[i].getGeometry().clone().transform('EPSG:3857', 'EPSG:4326');
try {
var str = JSON.stringify(coords.getCoordinates()[0]);
if (str.length > json.length) {
json = str;
}
} catch (e) {
console.log(e.message);
}
}
//put the coordinates in a html element
$('#map-gpx').val(json);
return $.parseJSON(json);
}
//=== set the map zoom level =======================================================================
function setMapZoom(zoom) {
map.getView().animate({
duration: 250,
zoom: zoom
});
}
//=== center the map on a coordinate ===============================================================
function setMapCenter(center, duration = 0) {
map.getView().animate({
duration: duration,
center: center
});
}
//=== make all the items on the map fit on the screen ==============================================
function zoomAndFitBounds(layer) {
var geom = ol.geom.Polygon.fromExtent(layer.getSource().getExtent())
geom.scale(1.1);
map.getView().fit(geom, { size: map.getSize() });
}
//=== add a layer to the map =======================================================================
function addLayerToMap(name) {
var layer = new ol.layer.Vector({
name: name,
zIndex: 600,
source: new ol.source.Vector()
});
//add it to the map
map.addLayer(layer);
return layer;
}
//=== remove a layer from the map ==================================================================
function removeLayerFromMap(name) {
map.getLayers().forEach(layer => {
if (layer && layer.get('name') === name) {
map.removeLayer(layer);
}
});
}
//=== reset the map to the default state ===========================================================
function resetMap() {
var layers = map.getLayers().getArray().slice();
layers.forEach(layer => {
//do not remove base and contexmenu layer
if (layer && (layer.get('name') === 'baselayer' || layer.get('name') === 'contextmenu')) {
return;
}
map.removeLayer(layer);
});
//reset zoom and map center
setMapZoom(map_default_zoomlevel);
setMapCenter(ol.proj.fromLonLat(cmsScriptVariables.dutch_map_center));
$('#map-gpx').val('');
}
//=== create the right click context menu ==========================================================
function createContextMenu() {
var icon_in = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItem9vbS1pbiI+PGNpcmNsZSBjeD0iMTEiIGN5PSIxMSIgcj0iOCI+PC9jaXJjbGU+PGxpbmUgeDE9IjIxIiB5MT0iMjEiIHgyPSIxNi42NSIgeTI9IjE2LjY1Ij48L2xpbmU+PGxpbmUgeDE9IjExIiB5MT0iOCIgeDI9IjExIiB5Mj0iMTQiPjwvbGluZT48bGluZSB4MT0iOCIgeTE9IjExIiB4Mj0iMTQiIHkyPSIxMSI+PC9saW5lPjwvc3ZnPg==';
var icon_out = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItem9vbS1vdXQiPjxjaXJjbGUgY3g9IjExIiBjeT0iMTEiIHI9IjgiPjwvY2lyY2xlPjxsaW5lIHgxPSIyMSIgeTE9IjIxIiB4Mj0iMTYuNjUiIHkyPSIxNi42NSI+PC9saW5lPjxsaW5lIHgxPSI4IiB5MT0iMTEiIHgyPSIxNCIgeTI9IjExIj48L2xpbmU+PC9zdmc+';
var icon_ctr = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJmZWF0aGVyIGZlYXRoZXItbWF4aW1pemUiPjxwYXRoIGQ9Ik04IDNINWEyIDIgMCAwIDAtMiAydjNtMTggMFY1YTIgMiAwIDAgMC0yLTJoLTNtMCAxOGgzYTIgMiAwIDAgMCAyLTJ2LTNNMyAxNnYzYTIgMiAwIDAgMCAyIDJoMyI+PC9wYXRoPjwvc3ZnPg==';
//menu items
var menuitems = [
{
text: 'Zoom in',
icon: icon_in,
callback: zoomIn
},
{
text: 'Zoom out',
icon: icon_out,
callback: zoomOut
},
{
text: 'Center map',
icon: icon_ctr,
callback: center
}
];
//create the context menu
var contextmenu = new ContextMenu({
items: menuitems
});
map.addControl(contextmenu);
//on menu open
contextmenu.on('open', function (evt) {
contextmenu.clear();
contextmenu.extend(menuitems);
contextmenu.extend(contextmenu.getDefaultItems());
});
//create a layer
var layer = new ol.layer.Vector({
source: new ol.source.Vector(),
name: 'contextmenu'
});
//add the layer to the map
map.addLayer(layer);
//on mouse move
map.on('pointermove', function (e) {
if (e.dragging) {
return;
}
var pixel = map.getEventPixel(e.originalEvent);
var hit = map.hasFeatureAtPixel(pixel);
map.getTargetElement().style.cursor = hit ? 'pointer' : '';
});
//context menu functionms
function center(obj) {
setMapCenter(obj.coordinate, 500);
}
function zoomIn(obj) {
setMapZoom(map.getView().getZoom() + 1);
}
function zoomOut(obj) {
setMapZoom(map.getView().getZoom() - 1);
}
}