/**
* Create Measure Control
* @type function
* @returns {function} See parameters of return function in {@link CONTROL_FACTORIES_measure}
*/
BKGWebMap.Control.createMeasure = function () {
return function (map, controlName, options, panel) {
var _this = this;
var mapId = map.getTarget();
// Check if control should be created
if (options.active === false) {
return undefined;
}
// If no panel exists and no other div ID is defined, do not create this control
if (!panel && (!options.div || options.div === '')) {
window.console.log(BKGWebMap.ERROR.noPanelNoDivForControl + controlName);
return undefined;
}
var target;
var inPanel = true;
if (options.div && options.div !== '') {
target = options.div;
inPanel = false;
} else {
target = panel.element.getElementsByClassName('bkgwebmap-panelbar')[0];
}
// Control title for panel
var title = 'Messen';
// Custom class
var customClass = '';
if (options.style && options.style !== '') {
customClass = ' ' + options.style;
}
// Tooltip position
var tooltipClass = 'bkgwebmap-paneltooltip bkgwebmap-paneltooltipleft';
var tooltipTextClass = 'bkgwebmap-paneltooltiptext bkgwebmap-paneltooltiptextleft';
if (inPanel && panel.getPanelPosition() === 'right') {
tooltipClass = 'bkgwebmap-paneltooltip bkgwebmap-paneltooltipright';
tooltipTextClass = 'bkgwebmap-paneltooltiptext bkgwebmap-paneltooltiptextright';
}
// Create DOM
var measure = document.createElement('div');
measure.className = 'bkgwebmap-measure';
var measureToggle = document.createElement('div');
measureToggle.className = 'bkgwebmap-measureToggle ' + tooltipClass + customClass;
measure.appendChild(measureToggle);
var measureTooltip = document.createElement('span');
measureTooltip.className = tooltipTextClass;
measureTooltip.innerHTML = title;
measureToggle.appendChild(measureTooltip);
var parser = new DOMParser();
var measureIcon = parser.parseFromString(BKGWebMap.PANEL_ICONS.MEASURE_AREA, 'text/xml');
measureIcon.documentElement.setAttribute('class', 'bkgwebmap-panelicons');
measureToggle.appendChild(measureIcon.documentElement);
var measureSidePanel = document.createElement('div');
measureSidePanel.className = 'bkgwebmap-sidemultiplepanel';
measure.appendChild(measureSidePanel);
measureSidePanel.style.position = 'relative';
if (inPanel) {
measureSidePanel.style.width = document.getElementById(mapId).getElementsByClassName('bkgwebmap-panelbar')[0].style.width;
if (panel.getPanelPosition() === 'right') {
measureSidePanel.style.right = '50px';
} else {
measureSidePanel.style.left = '50px';
}
measureSidePanel.style.top = '-35px';
}
measureSidePanel.style.display = 'none';
var measureDistance = document.createElement('div');
measureDistance.className = 'bkgwebmap-sidepanelbuttons bkgwebmap-measurebuttons bkgwebmap-measuredistance ' + tooltipClass;
var newNode = parser.parseFromString(BKGWebMap.PANEL_ICONS.MEASURE_DISTANCE, 'text/xml');
newNode.documentElement.setAttribute('class', 'bkgwebmap-sidepanelicons');
measureDistance.appendChild(newNode.documentElement);
measureSidePanel.appendChild(measureDistance);
var measureDistanceTooltip = document.createElement('span');
measureDistanceTooltip.className = tooltipTextClass;
measureDistanceTooltip.innerHTML = 'Strecke messen';
measureDistance.appendChild(measureDistanceTooltip);
var measureArea = document.createElement('div');
measureArea.className = 'bkgwebmap-sidepanelbuttons bkgwebmap-measurebuttons bkgwebmap-measurearea ' + tooltipClass;
measureArea.style.marginTop = '10px';
newNode = parser.parseFromString(BKGWebMap.PANEL_ICONS.MEASURE_AREA, 'text/xml');
newNode.documentElement.setAttribute('class', 'bkgwebmap-sidepanelicons');
measureArea.appendChild(newNode.documentElement);
measureSidePanel.appendChild(measureArea);
var measureAreaTooltip = document.createElement('span');
measureAreaTooltip.className = tooltipTextClass;
measureAreaTooltip.innerHTML = 'Fläche messen';
measureArea.appendChild(measureAreaTooltip);
if (inPanel) {
measureDistance.style.backgroundColor = '#407E40';
measureArea.style.backgroundColor = '#407E40';
}
// Show tooltip on hover and hide all other
function showHideTooltips(tooltip) {
var allTooltips = document.getElementById(mapId).getElementsByClassName('bkgwebmap-paneltooltiptext');
for (var i = 0; i < allTooltips.length; i++) {
allTooltips[i].style.visibility = '';
}
tooltip.style.visibility = 'visible';
setTimeout(function () {
tooltip.style.visibility = '';
}, 1200);
}
// Event listeners
measureToggle.addEventListener('click', function () {
_this.toggleSidePanels();
}, true);
measureArea.addEventListener('click', measureOn, false);
measureArea.addEventListener('mouseenter', function () {
showHideTooltips(measureAreaTooltip);
}, false);
measureDistance.addEventListener('click', measureOn, false);
measureDistance.addEventListener('mouseenter', function () {
showHideTooltips(measureDistanceTooltip);
}, false);
measureToggle.addEventListener('mouseenter', function () {
showHideTooltips(measureTooltip);
}, false);
function hightlightMeasureButton(type) {
if (type === 'area') {
measureArea.classList.add('bkgwebmap-measureactive');
removeStyleClass(measureDistance, 'bkgwebmap-measureactive');
} else if (type === 'distance') {
measureDistance.classList.add('bkgwebmap-measureactive');
removeStyleClass(measureArea, 'bkgwebmap-measureactive');
}
}
function removeStyleClass(element, cssClass) {
if (element.classList.contains(cssClass)) {
element.classList.remove(cssClass);
}
}
// Functionality
var measureControl = this;
this.closeSidePanel = function (print) {
if (!print) {
if (draw) {
measureClearResults();
addAttributeListener();
}
measureSidePanel.style.display = 'none';
} else {
if (draw) {
addAttributeListener();
}
measureSidePanel.style.display = 'none';
}
removeStyleClass(measure, 'bkgwebmap-panelactive');
removeStyleClass(measureArea, 'bkgwebmap-measureactive');
removeStyleClass(measureDistance, 'bkgwebmap-measureactive');
};
document.onkeydown = function (evt) {
evt = evt || window.event;
var isEscape = false;
if ('key' in evt) {
isEscape = (evt.key === 'Escape' || evt.key === 'Esc');
} else {
isEscape = (evt.keyCode === 27);
}
if (isEscape) {
if (draw) {
measureClearResults();
addAttributeListener();
}
}
};
function deactivateEdit() {
map.getControls().forEach(function (control) {
if (BKGWebMap.Control.Edit && control instanceof BKGWebMap.Control.Edit) {
control.removeEditInteractions();
}
});
}
/**
* Open/close panel with measure buttons
*/
this.toggleSidePanels = function () {
deactivateEdit();
if (inPanel) {
if (measure.classList.contains('bkgwebmap-panelactive')) {
measure.classList.remove('bkgwebmap-panelactive');
} else {
measure.classList.add('bkgwebmap-panelactive');
}
}
panel.closePanel();
if (measureSidePanel.style.display === 'none') {
measureSidePanel.style.display = 'block';
} else if (measureSidePanel.style.display === 'block') {
measureControl.closeSidePanel();
}
};
// Interaction for drawing
var draw;
// Layer for drawing
var source = new ol.source.Vector();
var vector = new ol.layer.Vector({
source: source,
measureLayer: true,
uniqueId: 'measurelayer',
style: new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(158, 11, 18, 0.2)'
}),
stroke: new ol.style.Stroke({
color: 'rgba(158, 11, 18, 1)',
width: 2
}),
image: new ol.style.Circle({
radius: 7,
fill: new ol.style.Fill({
color: '#ffcc33'
})
})
})
});
// Overlay to show the help messages
var helpTooltip;
// Overlay to show the measurement
var measureTooltipOverlay;
function removeAttributeListener() {
map.getControls().forEach(function (control) {
if (BKGWebMap.Control.ShowAttributes && control instanceof BKGWebMap.Control.ShowAttributes) {
map.un('click', control.clickAttributesActivate);
}
if (BKGWebMap.Control.GeoSearch && control instanceof BKGWebMap.Control.GeoSearch) {
map.un('click', control.geoSearchClickActivate);
}
if (BKGWebMap.Control.CopyCoordinates && control instanceof BKGWebMap.Control.CopyCoordinates) {
map.un('click', control.clickCopyCoordinatesActivate);
}
});
}
function addAttributeListener() {
map.getControls().forEach(function (control) {
if (BKGWebMap.Control.ShowAttributes && control instanceof BKGWebMap.Control.ShowAttributes) {
map.on('click', control.clickAttributesActivate);
}
if (BKGWebMap.Control.GeoSearch && control instanceof BKGWebMap.Control.GeoSearch) {
map.on('click', control.geoSearchClickActivate);
}
if (BKGWebMap.Control.CopyCoordinates && control instanceof BKGWebMap.Control.CopyCoordinates) {
map.on('click', control.clickCopyCoordinatesActivate);
}
});
}
function measureClearResults() {
var i;
map.removeInteraction(draw);
map.removeOverlay(helpTooltip);
source.clear();
// remove tooltips
var oldStaticTooltips = document.getElementById(mapId).getElementsByClassName('bkgwebmap-measureoverlay-tooltip-static');
if (oldStaticTooltips.length) {
for (i = 0; i < oldStaticTooltips.length; i++) {
oldStaticTooltips[i].parentNode.remove();
}
}
var oldMeasureTooltips = document.getElementById(mapId).getElementsByClassName('bkgwebmap-measureoverlay-tooltip-measure');
if (oldMeasureTooltips.length) {
for (i = 0; i < oldMeasureTooltips.length; i++) {
oldMeasureTooltips[i].parentNode.remove();
}
}
map.removeLayer(vector);
}
function measureOn() {
removeAttributeListener();
if (draw) {
measureClearResults();
}
var typeMeasure;
if (this.classList.contains('bkgwebmap-measurearea')) {
typeMeasure = 'Polygon';
hightlightMeasureButton('area');
} else {
typeMeasure = 'LineString';
hightlightMeasureButton('distance');
}
// Currently drawn feature
var sketch;
// The help tooltip element
var helpTooltipElement;
// The measure tooltip element
var measureTooltipElement;
// Message to show when the user is drawing a polygon
var continuePolygonMsg = 'Polygon-Stützpunkt setzen';
// Message to show when the user is drawing a line
var continueLineMsg = 'Linie-Stützpunkt setzen';
// Handle pointer move
var pointerMoveHandler = function (evt) {
if (evt.dragging) {
return;
}
var helpMsg = 'Klicken, um zu messen';
if (sketch) {
var geom = (sketch.getGeometry());
if (geom instanceof ol.geom.Polygon) {
helpMsg = continuePolygonMsg;
} else if (geom instanceof ol.geom.LineString) {
helpMsg = continueLineMsg;
}
}
helpTooltipElement.innerHTML = helpMsg;
helpTooltip.setPosition(evt.coordinate);
helpTooltipElement.classList.remove('hidden');
};
map.on('pointermove', pointerMoveHandler);
map.getViewport().addEventListener('mouseout', function () {
helpTooltipElement.classList.add('hidden');
});
var mapProjection = map.getView().getProjection();
var wgs84Sphere = new ol.Sphere(6378137);
// Format length output.
var formatLength = function (line) {
var length = 0;
var coordinates = line.getCoordinates();
for (var i = 0; i < coordinates.length - 1; i++) {
var c1 = ol.proj.transform(coordinates[i], mapProjection, 'EPSG:4326');
var c2 = ol.proj.transform(coordinates[i + 1], mapProjection, 'EPSG:4326');
length += wgs84Sphere.haversineDistance(c1, c2);
}
var output;
if (length > 100) {
output = (Math.round(length / 1000 * 100) / 100) +
' km';
} else {
output = (Math.round(length * 100) / 100) +
' m';
}
return output;
};
// Format area output.
var formatArea = function (polygon) {
var newPolygon = polygon.clone().transform(mapProjection, 'EPSG:4326');
var coordPolygon = newPolygon.getLinearRing(0).getCoordinates();
var area = Math.abs(wgs84Sphere.geodesicArea(coordPolygon));
var output;
if (area > 10000) {
output = (Math.round(area / 1000000 * 100) / 100) +
' km<sup>2</sup>';
} else {
output = (Math.round(area * 100) / 100) +
' m<sup>2</sup>';
}
return output;
};
function addInteraction() {
draw = new ol.interaction.Draw({
source: source,
type: typeMeasure,
style: new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(158, 11, 18, 0.2)'
}),
stroke: new ol.style.Stroke({
color: 'rgba(158, 11, 18, 1)',
width: 3
}),
image: new ol.style.Circle({
radius: 5,
stroke: new ol.style.Stroke({
color: 'rgba(158, 11, 18, 0.7)'
}),
fill: new ol.style.Fill({
color: 'rgba(255, 255, 255, 0.2)'
})
})
})
});
map.addInteraction(draw);
createMeasureTooltip();
createHelpTooltip();
var listener;
draw.on('drawstart', function (evt) {
var oldTooltip = document.getElementById(mapId).getElementsByClassName('bkgwebmap-measureoverlay-tooltip-static');
if (oldTooltip.length) {
for (var i = 0; i < oldTooltip.length; i++) {
oldTooltip[i].parentNode.remove();
}
}
source.clear();
map.removeLayer(vector);
evt.feature.setProperties({
id: 'measurefeature'
});
// Set sketch
sketch = evt.feature;
var tooltipCoord = evt.coordinate;
listener = sketch.getGeometry().on('change', function (event) {
var geom = event.target;
var output;
if (geom instanceof ol.geom.Polygon) {
output = formatArea(geom);
tooltipCoord = geom.getInteriorPoint().getCoordinates();
} else if (geom instanceof ol.geom.LineString) {
output = formatLength(geom);
tooltipCoord = geom.getLastCoordinate();
}
measureTooltipElement.innerHTML = output;
measureTooltipOverlay.setPosition(tooltipCoord);
});
}, this);
draw.on('drawend', function () {
measureTooltipElement.className = 'bkgwebmap-measureoverlay-tooltip bkgwebmap-measureoverlay-tooltip-static';
measureTooltipOverlay.setOffset([0, -30]);
// Unset sketch
sketch = null;
// Unset tooltip so that a new one can be created
measureTooltipElement = null;
createMeasureTooltip();
ol.Observable.unByKey(listener);
map.addLayer(vector);
}, this);
}
// Creates a new help tooltip
function createHelpTooltip() {
if (helpTooltipElement) {
helpTooltipElement.parentNode.removeChild(helpTooltipElement);
}
helpTooltipElement = document.createElement('div');
helpTooltipElement.className = 'bkgwebmap-measureoverlay-tooltip hidden';
helpTooltip = new ol.Overlay({
element: helpTooltipElement,
offset: [15, 0],
positioning: 'center-left'
});
map.addOverlay(helpTooltip);
}
// Creates a new measure tooltip
function createMeasureTooltip() {
if (measureTooltipElement) {
measureTooltipElement.parentNode.removeChild(measureTooltipElement);
}
measureTooltipElement = document.createElement('div');
measureTooltipElement.className = 'bkgwebmap-measureoverlay-tooltip bkgwebmap-measureoverlay-tooltip-measure';
measureTooltipOverlay = new ol.Overlay({
element: measureTooltipElement,
offset: [0, -50],
positioning: 'bottom-center'
});
map.addOverlay(measureTooltipOverlay);
}
addInteraction();
}
// Finalize control
ol.control.Control.call(this, {
element: measure,
target: target
});
};
};