1 2var map = new ol.Map({ 3 target: 'map', 4 renderer: 'canvas', 5 layers: layersList, 6 view: new ol.View({ 7 maxZoom: 28, minZoom: 1 8 }) 9}); 10 11//initial view - epsg:3857 coordinates if not "Match project CRS" 12map.getView().fit([-1467867.051607, 944707.532562, -1465298.767456, 946171.784070], map.getSize()); 13 14//full zooms only 15map.getView().setProperties({constrainResolution: true}); 16 17//change cursor 18function pointerOnFeature(evt) { 19 if (evt.dragging) { 20 return; 21 } 22 var hasFeature = map.hasFeatureAtPixel(evt.pixel, { 23 layerFilter: function(layer) { 24 return layer && (layer.get("interactive")); 25 } 26 }); 27 map.getViewport().style.cursor = hasFeature ? "pointer" : ""; 28} 29map.on('pointermove', pointerOnFeature); 30function styleCursorMove() { 31 map.on('pointerdrag', function() { 32 map.getViewport().style.cursor = "move"; 33 }); 34 map.on('pointerup', function() { 35 map.getViewport().style.cursor = "default"; 36 }); 37} 38styleCursorMove(); 39 40////small screen definition 41 var hasTouchScreen = map.getViewport().classList.contains('ol-touch'); 42 var isSmallScreen = window.innerWidth < 650; 43 44////controls container 45 46 //top left container 47 var topLeftContainer = new ol.control.Control({ 48 element: (() => { 49 var topLeftContainer = document.createElement('div'); 50 topLeftContainer.id = 'top-left-container'; 51 return topLeftContainer; 52 })(), 53 }); 54 map.addControl(topLeftContainer) 55 56 //bottom left container 57 var bottomLeftContainer = new ol.control.Control({ 58 element: (() => { 59 var bottomLeftContainer = document.createElement('div'); 60 bottomLeftContainer.id = 'bottom-left-container'; 61 return bottomLeftContainer; 62 })(), 63 }); 64 map.addControl(bottomLeftContainer) 65 66 //top right container 67 var topRightContainer = new ol.control.Control({ 68 element: (() => { 69 var topRightContainer = document.createElement('div'); 70 topRightContainer.id = 'top-right-container'; 71 return topRightContainer; 72 })(), 73 }); 74 map.addControl(topRightContainer) 75 76 //bottom right container 77 var bottomRightContainer = new ol.control.Control({ 78 element: (() => { 79 var bottomRightContainer = document.createElement('div'); 80 bottomRightContainer.id = 'bottom-right-container'; 81 return bottomRightContainer; 82 })(), 83 }); 84 map.addControl(bottomRightContainer) 85 86//popup 87var container = document.getElementById('popup'); 88var content = document.getElementById('popup-content'); 89var closer = document.getElementById('popup-closer'); 90var sketch; 91 92function stopMediaInPopup() { 93 var mediaElements = container.querySelectorAll('audio, video'); 94 mediaElements.forEach(function(media) { 95 media.pause(); 96 media.currentTime = 0; 97 }); 98} 99closer.onclick = function() { 100 container.style.display = 'none'; 101 closer.blur(); 102 stopMediaInPopup(); 103 return false; 104}; 105var overlayPopup = new ol.Overlay({ 106 element: container, 107 autoPan: true 108}); 109map.addOverlay(overlayPopup) 110 111 112var NO_POPUP = 0 113var ALL_FIELDS = 1 114 115/** 116 * Returns either NO_POPUP, ALL_FIELDS or the name of a single field to use for 117 * a given layer 118 * @param layerList {Array} List of ol.Layer instances 119 * @param layer {ol.Layer} Layer to find field info about 120 */ 121function getPopupFields(layerList, layer) { 122 // Determine the index that the layer will have in the popupLayers Array, 123 // if the layersList contains more items than popupLayers then we need to 124 // adjust the index to take into account the base maps group 125 var idx = layersList.indexOf(layer) - (layersList.length - popupLayers.length); 126 return popupLayers[idx]; 127} 128 129//highligth collection 130var collection = new ol.Collection(); 131var featureOverlay = new ol.layer.Vector({ 132 map: map, 133 source: new ol.source.Vector({ 134 features: collection,
135 useSpatialIndex: false // optional, might improve performance 136 }), 137 style: [new ol.style.Style({ 138 stroke: new ol.style.Stroke({ 139 color: '#f00', 140 width: 1 141 }), 142 fill: new ol.style.Fill({ 143 color: 'rgba(255,0,0,0.1)' 144 }), 145 })], 146 updateWhileAnimating: true, // optional, for instant visual feedback 147 updateWhileInteracting: true // optional, for instant visual feedback 148}); 149 150var doHighlight = true; 151var doHover = true; 152 153function createPopupField(currentFeature, currentFeatureKeys, layer) { 154 var popupText = ''; 155 for (var i = 0; i < currentFeatureKeys.length; i++) { 156 if (currentFeatureKeys[i] != 'geometry' && currentFeatureKeys[i] != 'layerObject' && currentFeatureKeys[i] != 'idO') { 157 var popupField = ''; 158 if (layer.get('fieldLabels')[currentFeatureKeys[i]] == "hidden field") { 159 continue; 160 } else if (layer.get('fieldLabels')[currentFeatureKeys[i]] == "inline label - visible with data") { 161 if (currentFeature.get(currentFeatureKeys[i]) == null) { 162 continue; 163 } 164 } 165 if (layer.get('fieldLabels')[currentFeatureKeys[i]] == "inline label - always visible" || 166 layer.get('fieldLabels')[currentFeatureKeys[i]] == "inline label - visible with data") { 167 popupField += '<th>' + layer.get('fieldAliases')[currentFeatureKeys[i]] + '</th><td>'; 168 } else { 169 popupField += '<td colspan="2">'; 170 } 171 if (layer.get('fieldLabels')[currentFeatureKeys[i]] == "header label - visible with data") { 172 if (currentFeature.get(currentFeatureKeys[i]) == null) { 173 continue; 174 } 175 } 176 if (layer.get('fieldLabels')[currentFeatureKeys[i]] == "header label - always visible" || 177 layer.get('fieldLabels')[currentFeatureKeys[i]] == "header label - visible with data") { 178 popupField += '<strong>' + layer.get('fieldAliases')[currentFeatureKeys[i]] + '</strong><br />'; 179 } 180 if (layer.get('fieldImages')[currentFeatureKeys[i]] != "ExternalResource") { 181 popupField += (currentFeature.get(currentFeatureKeys[i]) != null ? autolinker.link(currentFeature.get(currentFeatureKeys[i]).toLocaleString()) + '</td>' : ''); 182 } else { 183 var fieldValue = currentFeature.get(currentFeatureKeys[i]); 184 if (/\.(gif|jpg|jpeg|tif|tiff|png|avif|webp|svg)$/i.test(fieldValue)) { 185 popupField += (fieldValue != null ? '<img src="images/' + fieldValue.replace(/[\\\/:]/g, '_').trim() + '" /></td>' : ''); 186 } else if (/\.(mp4|webm|ogg|avi|mov|flv)$/i.test(fieldValue)) { 187 popupField += (fieldValue != null ? '<video controls><source src="images/' + fieldValue.replace(/[\\\/:]/g, '_').trim() + '" type="video/mp4">Il tuo browser non supporta il tag video.</video></td>' : ''); 188 } else if (/\.(mp3|wav|ogg|aac|flac)$/i.test(fieldValue)) { 189 popupField += (fieldValue != null ? '<audio controls><source src="images/' + fieldValue.replace(/[\\\/:]/g, '_').trim() + '" type="audio/mpeg">Il tuo browser non supporta il tag audio.</audio></td>' : ''); 190 } else { 191 popupField += (fieldValue != null ? autolinker.link(fieldValue.toLocaleString()) + '</td>' : ''); 192 } 193 } 194 popupText += '<tr>' + popupField + '</tr>'; 195 } 196 } 197 return popupText; 198} 199 200var highlight; 201var autolinker = new Autolinker({truncate: {length: 30, location: 'smart'}}); 202 203function onPointerMove(evt) { 204 if (!doHover && !doHighlight) { 205 return; 206 } 207 var pixel = map.getEventPixel(evt.originalEvent); 208 var coord = evt.coordinate; 209 var currentFeature; 210 var currentLayer; 211 var currentFeatureKeys; 212 var clusteredFeatures; 213 var clusterLength; 214 var popupText = '<ul>'; 215 216 // Collect all features and their layers at the pixel 217 var featuresAndLayers = []; 218 map.forEachFeatureAtPixel(pixel, function(feature, layer) { 219 if (layer && feature instanceof ol.Feature && (layer.get("interactive") || layer.get("interactive") === undefined)) { 220 featuresAndLayers.push({ feature, layer }); 221 } 222 });
223 224 // Iterate over the features and layers in reverse order 225 for (var i = featuresAndLayers.length - 1; i >= 0; i--) { 226 var feature = featuresAndLayers[i].feature; 227 var layer = featuresAndLayers[i].layer; 228 var doPopup = false; 229 for (k in layer.get('fieldImages')) { 230 if (layer.get('fieldImages')[k] != "Hidden") { 231 doPopup = true; 232 } 233 } 234 currentFeature = feature; 235 currentLayer = layer; 236 clusteredFeatures = feature.get("features"); 237 if (clusteredFeatures) { 238 clusterLength = clusteredFeatures.length; 239 } 240 if (typeof clusteredFeatures !== "undefined") { 241 if (doPopup) { 242 for(var n=0; n<clusteredFeatures.length; n++) { 243 currentFeature = clusteredFeatures[n]; 244 currentFeatureKeys = currentFeature.getKeys(); 245 popupText += '<li><table>' 246 popupText += '<a>' + '<b>' + layer.get('popuplayertitle') + '</b>' + '</a>'; 247 popupText += createPopupField(currentFeature, currentFeatureKeys, layer); 248 popupText += '</table></li>'; 249 } 250 } 251 } else { 252 currentFeatureKeys = currentFeature.getKeys(); 253 if (doPopup) { 254 popupText += '<li><table>'; 255 popupText += '<a>' + '<b>' + layer.get('popuplayertitle') + '</b>' + '</a>'; 256 popupText += createPopupField(currentFeature, currentFeatureKeys, layer); 257 popupText += '</table></li>'; 258 } 259 } 260 } 261 262 if (popupText == '<ul>') { 263 popupText = ''; 264 } else { 265 popupText += '</ul>'; 266 } 267 268 if (doHighlight) { 269 if (currentFeature !== highlight) { 270 if (highlight) { 271 featureOverlay.getSource().removeFeature(highlight); 272 } 273 if (currentFeature) { 274 var featureStyle 275 if (typeof clusteredFeatures == "undefined") { 276 var style = currentLayer.getStyle(); 277 var styleFunction = typeof style === 'function' ? style : function() { return style; }; 278 featureStyle = styleFunction(currentFeature)[0]; 279 } else { 280 featureStyle = currentLayer.getStyle().toString(); 281 } 282 283 if (currentFeature.getGeometry().getType() == 'Point' || currentFeature.getGeometry().getType() == 'MultiPoint') { 284 var radius 285 if (typeof clusteredFeatures == "undefined") { 286 radius = featureStyle.getImage().getRadius(); 287 } else { 288 radius = parseFloat(featureStyle.split('radius')[1].split(' ')[1]) + clusterLength; 289 } 290 291 highlightStyle = new ol.style.Style({ 292 image: new ol.style.Circle({ 293 fill: new ol.style.Fill({ 294 color: "rgba(255, 255, 0, 1.00)" 295 }), 296 radius: radius 297 }) 298 }) 299 } else if (currentFeature.getGeometry().getType() == 'LineString' || currentFeature.getGeometry().getType() == 'MultiLineString') { 300 301 var featureWidth = featureStyle.getStroke().getWidth(); 302 303 highlightStyle = new ol.style.Style({ 304 stroke: new ol.style.Stroke({ 305 color: 'rgba(255, 255, 0, 1.00)', 306 lineDash: null, 307 width: featureWidth 308 }) 309 }); 310 311 } else { 312 highlightStyle = new ol.style.Style({ 313 fill: new ol.style.Fill({ 314 color: 'rgba(255, 255, 0, 1.00)' 315 }) 316 }) 317 } 318 featureOverlay.getSource().addFeature(currentFeature); 319 featureOverlay.setStyle(highlightStyle); 320 } 321 highlight = currentFeature; 322 } 323 } 324 325 if (doHover) { 326 if (popupText) { 327 content.innerHTML = popupText; 328 container.style.display = 'block'; 329 overlayPopup.setPosition(coord); 330 } else { 331 container.style.display = 'none'; 332 closer.blur(); 333 } 334 } 335}; 336 337map.on('pointermove', onPointerMove); 338 339var popupContent = ''; 340var popupCoord = null; 341var featuresPopupActive = false; 342 343function updatePopup() { 344 if (popupContent) { 345 content.innerHTML = popupContent; 346 container.style.display = 'block'; 347 overlayPopup.setPosition(popupCoord); 348 } else { 349 container.style.display = 'none'; 350 closer.blur(); 351 stopMediaInPopup(); 352 } 353} 354 355function onSingleClickFeatures(evt) { 356 if (doHover || sketch) { 357 return; 358 } 359 if (!featuresPopupActive) { 360 featuresPopupActive = true; 361 } 362 var pixel = map.getEventPixel(evt.originalEvent); 363 var coord = evt.coordinate; 364 var currentFeature;
365 var currentFeatureKeys; 366 var clusteredFeatures; 367 var popupText = '<ul>'; 368 369 map.forEachFeatureAtPixel(pixel, function(feature, layer) { 370 if (layer && feature instanceof ol.Feature && (layer.get("interactive") || layer.get("interactive") === undefined)) { 371 var doPopup = false; 372 for (var k in layer.get('fieldImages')) { 373 if (layer.get('fieldImages')[k] !== "Hidden") { 374 doPopup = true; 375 } 376 } 377 currentFeature = feature; 378 clusteredFeatures = feature.get("features"); 379 if (typeof clusteredFeatures !== "undefined") { 380 if (doPopup) { 381 for(var n = 0; n < clusteredFeatures.length; n++) { 382 currentFeature = clusteredFeatures[n]; 383 currentFeatureKeys = currentFeature.getKeys(); 384 popupText += '<li><table>'; 385 popupText += '<a><b>' + layer.get('popuplayertitle') + '</b></a>'; 386 popupText += createPopupField(currentFeature, currentFeatureKeys, layer); 387 popupText += '</table></li>'; 388 } 389 } 390 } else { 391 currentFeatureKeys = currentFeature.getKeys(); 392 if (doPopup) { 393 popupText += '<li><table>'; 394 popupText += '<a><b>' + layer.get('popuplayertitle') + '</b></a>'; 395 popupText += createPopupField(currentFeature, currentFeatureKeys, layer); 396 popupText += '</table>'; 397 } 398 } 399 } 400 }); 401 if (popupText === '<ul>') { 402 popupText = ''; 403 } else { 404 popupText += '</ul>'; 405 } 406 407 popupContent = popupText; 408 popupCoord = coord; 409 updatePopup(); 410} 411 412function onSingleClickWMS(evt) { 413 if (doHover || sketch) { 414 return; 415 } 416 if (!featuresPopupActive) { 417 popupContent = ''; 418 } 419 var coord = evt.coordinate; 420 var viewProjection = map.getView().getProjection(); 421 var viewResolution = map.getView().getResolution(); 422 423 for (var i = 0; i < wms_layers.length; i++) { 424 if (wms_layers[i][1] && wms_layers[i][0].getVisible()) { 425 var url = wms_layers[i][0].getSource().getFeatureInfoUrl( 426 evt.coordinate, viewResolution, viewProjection, { 427 'INFO_FORMAT': 'text/html', 428 }); 429 if (url) { 430 const wmsTitle = wms_layers[i][0].get('popuplayertitle'); 431 var ldsRoller = '<div class="roller-switcher" style="height: 25px; width: 25px;"></div>'; 432 433 popupCoord = coord; 434 popupContent += ldsRoller; 435 updatePopup(); 436 437 var timeoutPromise = new Promise((resolve, reject) => { 438 setTimeout(() => { 439 reject(new Error('Timeout exceeded')); 440 }, 5000); // (5 second) 441 }); 442 443 // Function to try fetch with different option 444 function tryFetch(urls) { 445 if (urls.length === 0) { 446 return Promise.reject(new Error('All fetch attempts failed')); 447 } 448 return fetch(urls[0]) 449 .then((response) => { 450 if (response.ok) { 451 return response.text(); 452 } else { 453 throw new Error('Fetch failed'); 454 } 455 }) 456 .catch(() => tryFetch(urls.slice(1))); // Try next URL 457 } 458 459 // List of URLs to try 460 // The first URL is the original, the second is the encoded version, and the third is the proxy 461 const urlsToTry = [ 462 url, 463 encodeURIComponent(url), 464 'https://api.allorigins.win/raw?url=' + encodeURIComponent(url) 465 ]; 466 467 Promise.race([tryFetch(urlsToTry), timeoutPromise]) 468 .then((html) => { 469 if (html.indexOf('<table') !== -1) { 470 popupContent += '<a><b>' + wmsTitle + '</b></a>'; 471 popupContent += html + '<p></p>'; 472 updatePopup(); 473 } 474 }) 475 .finally(() => { 476 setTimeout(() => { 477 var loaderIcon = document.querySelector('.roller-switcher'); 478 if (loaderIcon) loaderIcon.remove(); 479 }, 500); // (0.5 second) 480 }); 481 } 482 } 483 } 484} 485 486map.on('singleclick', onSingleClickFeatures); 487map.on('singleclick', onSingleClickWMS); 488 489//get container 490var topLeftContainerDiv = document.getElementById('top-left-container') 491var bottomLeftContainerDiv = document.getElementById('bottom-left-container') 492var topRightContainerDiv = document.getElementById('top-right-container') 493var bottomRightContainerDiv = document.getElementById('bottom-right-container') 494 495//title 496 497//abstract 498 499 500//geolocate 501 502 503 504//measurement 505let measuring = false; 506 507 const measureButton = document.createElement('button'); 508 measureButton.className = 'measure-button fas fa-ruler'; 509 measureButton.title = 'Measure'; 510 511 const measureControl = document.createElement('div'); 512 measureControl.className = 'ol-unselectable ol-control measure-control'; 513 measureControl.appendChild(measureButton); 514 map.getTargetElement().appendChild(measureControl); 515 516 // Event handler 517 function handleMeasure() { 518 if (!measuring) { 519 selectLabel.style.display = ""; 520 map.addInteraction(draw); 521 createHelpTooltip(); 522 createMeasureTooltip(); 523 measuring = true; 524 } else { 525 selectLabel.style.display = "none"; 526 map.removeInteraction(draw); 527 map.removeOverlay(helpTooltip); 528 map.removeOverlay(measureTooltip); 529 const staticTooltips = document.getElementsByClassName("tooltip-static"); 530 while (staticTooltips.length > 0) { 531 staticTooltips[0].parentNode.removeChild(staticTooltips[0]); 532 } 533 measureLayer.getSource().clear(); 534 sketch = null; 535 measuring = false; 536 } 537 } 538 539 measureButton.addEventListener('click', handleMeasure); 540 measureButton.addEventListener('touchstart', handleMeasure); 541 542 map.on('pointermove', function(evt) { 543 if (evt.dragging) { 544 return; 545 } 546 if (measuring) { 547 /** @type {string} */ 548 var helpMsg = 'Click to start drawing'; 549 if (sketch) { 550 var geom = (sketch.getGeometry()); 551 if (geom instanceof ol.geom.Polygon) { 552 helpMsg = continuePolygonMsg; 553 } else if (geom instanceof ol.geom.LineString) { 554 helpMsg = continueLineMsg; 555 } 556 } 557 helpTooltipElement.innerHTML = helpMsg; 558 helpTooltip.setPosition(evt.coordinate); 559 } 560 });
561 562 563 var selectLabel = document.createElement("label"); 564 selectLabel.innerHTML = " Measure: "; 565 566 var typeSelect = document.createElement("select"); 567 typeSelect.id = "type"; 568 569 var measurementOption = [ 570 { value: "LineString", description: "Length" }, 571 { value: "Polygon", description: "Area" } 572 ]; 573 measurementOption.forEach(function (option) { 574 var optionElement = document.createElement("option"); 575 optionElement.value = option.value; 576 optionElement.text = option.description; 577 typeSelect.appendChild(optionElement); 578 }); 579 580 selectLabel.appendChild(typeSelect); 581 measureControl.appendChild(selectLabel); 582 583 selectLabel.style.display = "none"; 584 /** 585 * Currently drawn feature. 586 * @type {ol.Feature} 587 */ 588 589 /** 590 * The help tooltip element. 591 * @type {Element} 592 */ 593 var helpTooltipElement; 594 595 596 /** 597 * Overlay to show the help messages. 598 * @type {ol.Overlay} 599 */ 600 var helpTooltip; 601 602 603 /** 604 * The measure tooltip element. 605 * @type {Element} 606 */ 607 var measureTooltipElement; 608 609 610 /** 611 * Overlay to show the measurement. 612 * @type {ol.Overlay} 613 */ 614 var measureTooltip; 615 616 617 /** 618 * Message to show when the user is drawing a line. 619 * @type {string} 620 */ 621 var continueLineMsg = 'Click to continue drawing the line'; 622 623 624 625 /** 626 * Message to show when the user is drawing a polygon. 627 * @type {string} 628 */ 629 var continuePolygonMsg = "1click continue, 2click close"; 630 631 632 var typeSelect = document.getElementById("type"); 633 var typeSelectForm = document.getElementById("form_measure"); 634 635 typeSelect.onchange = function (e) { 636 map.removeInteraction(draw); 637 addInteraction(); 638 map.addInteraction(draw); 639 }; 640 641 var measureLineStyle = new ol.style.Style({ 642 stroke: new ol.style.Stroke({ 643 color: "rgba(0, 0, 255)", //blu 644 lineDash: [10, 10], 645 width: 4 646 }), 647 image: new ol.style.Circle({ 648 radius: 6, 649 stroke: new ol.style.Stroke({ 650 color: "rgba(255, 255, 255)", 651 width: 1 652 }), 653 }) 654 }); 655 656 var measureLineStyle2 = new ol.style.Style({ 657 stroke: new ol.style.Stroke({ 658 color: "rgba(255, 255, 255)", 659 lineDash: [10, 10], 660 width: 2 661 }), 662 image: new ol.style.Circle({ 663 radius: 5, 664 stroke: new ol.style.Stroke({ 665 color: "rgba(0, 0, 255)", 666 width: 1 667 }), 668 fill: new ol.style.Fill({ 669 color: "rgba(255, 204, 51, 0.4)", 670 }), 671 }) 672 }); 673 674 var labelStyle = new ol.style.Style({ 675 text: new ol.style.Text({ 676 font: "14px Calibri,sans-serif", 677 fill: new ol.style.Fill({ 678 color: "rgba(0, 0, 0, 1)" 679 }), 680 stroke: new ol.style.Stroke({ 681 color: "rgba(255, 255, 255, 1)", 682 width: 3 683 }) 684 }) 685 }); 686 687 var labelStyleCache = []; 688 689 var styleFunction = function (feature, type) { 690 var styles = [measureLineStyle, measureLineStyle2]; 691 var geometry = feature.getGeometry(); 692 var type = geometry.getType(); 693 var lineString; 694 if (!type || type === type) { 695 if (type === "Polygon") { 696 lineString = new ol.geom.LineString(geometry.getCoordinates()[0]); 697 } else if (type === "LineString") { 698 lineString = geometry; 699 } 700 } 701 if (lineString) { 702 var count = 0; 703 lineString.forEachSegment(function (a, b) { 704 var segment = new ol.geom.LineString([a, b]); 705 var label = formatLength(segment); 706 if (labelStyleCache.length - 1 < count) { 707 labelStyleCache.push(labelStyle.clone()); 708 } 709 labelStyleCache[count].setGeometry(segment); 710 labelStyleCache[count].getText().setText(label); 711 styles.push(labelStyleCache[count]); 712 count++; 713 }); 714 } 715 return styles; 716 }; 717 var source = new ol.source.Vector(); 718 719 var measureLayer = new ol.layer.Vector({ 720 source: source, 721 displayInLayerSwitcher: false, 722 style: function (feature) { 723 labelStyleCache = []; 724 return styleFunction(feature); 725 } 726 }); 727 728 map.addLayer(measureLayer); 729 730 var draw; // global so we can remove it later 731 function addInteraction() { 732 var type = typeSelect.value; 733 draw = new ol.interaction.Draw({ 734 source: source, 735 type: /** @type {ol.geom.GeometryType} */ (type), 736 style: function (feature) { 737 return styleFunction(feature, type); 738 } 739 }); 740 741 var listener; 742 draw.on('drawstart', 743 function(evt) { 744 // set sketch 745 sketch = evt.feature; 746 747 /** @type {ol.Coordinate|undefined} */ 748 var tooltipCoord = evt.coordinate; 749 750 listener = sketch.getGeometry().on('change', function(evt) { 751 var geom = evt.target; 752 var output; 753 if (geom instanceof ol.geom.Polygon) { 754 output = formatArea(/** @type {ol.geom.Polygon} */ (geom)); 755 tooltipCoord = geom.getInteriorPoint().getCoordinates();
756 } else if (geom instanceof ol.geom.LineString) { 757 output = formatLength(/** @type {ol.geom.LineString} */ (geom)); 758 tooltipCoord = geom.getLastCoordinate(); 759 } 760 measureTooltipElement.innerHTML = output; 761 measureTooltip.setPosition(tooltipCoord); 762 }); 763 }, this); 764 765 draw.on('drawend', 766 function(evt) { 767 measureTooltipElement.className = 'tooltip tooltip-static'; 768 measureTooltip.setOffset([0, -7]); 769 // unset sketch 770 sketch = null; 771 // unset tooltip so that a new one can be created 772 measureTooltipElement = null; 773 createMeasureTooltip(); 774 ol.Observable.unByKey(listener); 775 }, this); 776 } 777 778 779 /** 780 * Creates a new help tooltip 781 */ 782 function createHelpTooltip() { 783 if (helpTooltipElement) { 784 helpTooltipElement.parentNode.removeChild(helpTooltipElement); 785 } 786 helpTooltipElement = document.createElement('div'); 787 helpTooltipElement.className = 'tooltip hidden'; 788 helpTooltip = new ol.Overlay({ 789 element: helpTooltipElement, 790 offset: [15, 0], 791 positioning: 'center-left' 792 }); 793 map.addOverlay(helpTooltip); 794 } 795 796 797 /** 798 * Creates a new measure tooltip 799 */ 800 function createMeasureTooltip() { 801 if (measureTooltipElement) { 802 measureTooltipElement.parentNode.removeChild(measureTooltipElement); 803 } 804 measureTooltipElement = document.createElement('div'); 805 measureTooltipElement.className = 'tooltip tooltip-measure'; 806 measureTooltip = new ol.Overlay({ 807 element: measureTooltipElement, 808 offset: [0, -15], 809 positioning: 'bottom-center' 810 }); 811 map.addOverlay(measureTooltip); 812 } 813 814 815 /** 816 * format length output 817 * @param {ol.geom.LineString} line 818 * @return {string} 819 */ 820 var formatLength = function(line) { 821 var length; 822 var coordinates = line.getCoordinates(); 823 length = 0; 824 var sourceProj = map.getView().getProjection(); 825 for (var i = 0, ii = coordinates.length - 1; i < ii; ++i) { 826 var c1 = ol.proj.transform(coordinates[i], sourceProj, 'EPSG:4326'); 827 var c2 = ol.proj.transform(coordinates[i + 1], sourceProj, 'EPSG:4326'); 828 length += ol.sphere.getDistance(c1, c2); 829 } 830 var output; 831 if (length > 100) { 832 output = (Math.round(length / 1000 * 100) / 100) + 833 ' ' + 'km'; 834 } else { 835 output = (Math.round(length * 100) / 100) + 836 ' ' + 'm'; 837 } 838 return output; 839 }; 840 841 /** 842 * Format area output. 843 * @param {ol.geom.Polygon} polygon The polygon. 844 * @return {string} Formatted area. 845 */ 846 var formatArea = function (polygon) { 847 var sourceProj = map.getView().getProjection(); 848 var geom = polygon.clone().transform(sourceProj, 'EPSG:3857'); 849 var area = Math.abs(ol.sphere.getArea(geom)); 850 var output; 851 if (area > 1000000) { 852 output = Math.round((area / 1000000) * 1000) / 1000 + ' ' + 'km<sup>2</sup>'; 853 } else { 854 output = Math.round(area * 100) / 100 + ' ' + 'm<sup>2</sup>'; 855 } 856 return output.replace('.', ','); 857 }; 858 859 addInteraction(); 860 861 var parentElement = document.querySelector(".measure-control"); 862 var elementToMove = document.getElementById("form_measure"); 863 if (elementToMove && parentElement) { 864 parentElement.insertBefore(elementToMove, parentElement.firstChild); 865 } 866 867 868//geocoder 869 870 //Layer to represent the point of the geocoded address 871 var geocoderLayer = new ol.layer.Vector({ 872 source: new ol.source.Vector(), 873 }); 874 map.addLayer(geocoderLayer); 875 var vectorSource = geocoderLayer.getSource(); 876 877 //Variable used to store the coordinates of geocoded addresses 878 var obj2 = { 879 value: '', 880 letMeKnow() { 881 //console.log(`Geocoded position: ${this.gcd}`); 882 }, 883 get gcd() { 884 return this.value; 885 }, 886 set gcd(value) { 887 this.value = value; 888 this.letMeKnow(); 889 } 890 } 891 892 var obj = { 893 value: '', 894 get label() { 895 return this.value; 896 }, 897 set label(value) { 898 this.value = value; 899 } 900 } 901 902 // Function to handle the selected address 903 function onSelected(feature) { 904 obj.label = feature; 905 input.value = typeof obj.label.properties.label === "undefined"? obj.label.properties.display_name : obj.label.properties.label; 906 var coordinates = ol.proj.transform( 907 [feature.geometry.coordinates[0], feature.geometry.coordinates[1]], 908 "EPSG:4326", 909 map.getView().getProjection() 910 ); 911 vectorSource.clear(true); 912 obj2.gcd = [feature.geometry.coordinates[0], feature.geometry.coordinates[1]]; 913 var marker = new ol.Feature(new ol.geom.Point(coordinates)); 914 var zIndex = 1; 915 marker.setStyle(new ol.style.Style({ 916 image: new ol.style.Icon(({ 917 anchor: [0.5, 1], 918 anchorXUnits: 'fraction', 919 anchorYUnits: 'fraction', 920 scale: 0.7, 921 opacity: 1, 922 src: "./resources/marker.png", 923 zIndex: zIndex 924 })), 925 zIndex: zIndex 926 })); 927 vectorSource.addFeature(marker); 928 map.getView().setCenter(coordinates); 929 map.getView().setZoom(18); 930 } 931 932 // Format the result in the autocomplete search bar 933 var formatResult = function (feature, el) { 934 var title = document.createElement("strong"); 935 el.appendChild(title); 936 var detailsContainer = document.createElement("small"); 937 el.appendChild(detailsContainer); 938 var details = []; 939 title.innerHTML = feature.properties.label || feature.properties.display_name; 940 var types = { 941 housenumber: "numéro", 942 street: "rue", 943 locality: "lieu-dit", 944 municipality: "commune", 945 }; 946 if ( 947 feature.properties.city && 948 feature.properties.city !== feature.properties.name 949 ) { 950 details.push(feature.properties.city); 951 } 952 if (feature.properties.context) { 953 details.push(feature.properties.context); 954 } 955 detailsContainer.innerHTML = details.join(", "); 956 }; 957 958 // Define a class to create the control button for the search bar in a div tag 959 class AddDomControl extends ol.control.Control { 960 constructor(elementToAdd, opt_options) { 961 const options = opt_options || {}; 962 963 const element = document.createElement("div"); 964 if (options.className) { 965 element.className = options.className; 966 } 967 element.appendChild(elementToAdd); 968 969 super({ 970 element: element, 971 target: options.target, 972 }); 973 } 974 } 975 976 // Function to show you can do something with the returned elements 977 function myHandler(featureCollection) { 978 //console.log(featureCollection); 979 } 980 981 // URL for API 982 const url = {"Nominatim OSM": "https://nominatim.openstreetmap.org/search?format=geojson&addressdetails=1&", 983 "France BAN": "https://api-adresse.data.gouv.fr/search/?"} 984 var API_URL = "//api-adresse.data.gouv.fr"; 985 986 // Create search by adresses component 987 var containers = new Photon.Search({ 988 resultsHandler: myHandler, 989 onSelected: onSelected, 990 placeholder: "Search an address", 991 formatResult: formatResult, 992 //url: API_URL + "/search/?", 993 url: url["Nominatim OSM"], 994 position: "topright", 995 // ,includePosition: function() { 996 // return ol.proj.transform( 997 // map.getView().getCenter(), 998 // map.getView().getProjection(), //'EPSG:3857', 999 // 'EPSG:4326' 1000 // ); 1001 // } 1002 }); 1003 1004 // Add the created DOM element within the map 1005 //var left = document.getElementById("top-left-container"); 1006 var controlGeocoder = new AddDomControl(containers, { 1007 className: "photon-geocoder-autocomplete ol-unselectable ol-control", 1008 }); 1009 map.addControl(controlGeocoder); 1010 var search = document.getElementsByClassName("photon-geocoder-autocomplete ol-unselectable ol-control")[0]; 1011 search.style.display = "flex"; 1012 1013 // Create the new button element 1014 var button = document.createElement("button"); 1015 button.type = "button"; 1016 button.id = "gcd-button-control"; 1017 button.className = "gcd-gl-btn fa fa-search leaflet-control"; 1018 1019 // Ajouter le bouton à l'élément parent 1020 search.insertBefore(button, search.firstChild); 1021 last = search.lastChild; 1022 last.style.display = "none"; 1023 button.addEventListener("click", function (e) { 1024 if (last.style.display === "none") { 1025 last.style.display = "block"; 1026 } else { 1027 last.style.display = "none"; 1028 } 1029 }); 1030 input = document.getElementsByClassName("photon-input")[0]; 1031 //var searchbar = document.getElementsByClassName("photon-geocoder-autocomplete ol-unselectable ol-control")[0] 1032 //left.appendChild(searchbar); 1033 1034 1035//layer search 1036 1037var searchLayer = new SearchLayer({ 1038 layer: lyr_Rokupa_1, 1039 colName: 'PAP ID', 1040 zoom: 10, 1041 collapsed: true, 1042 map: map, 1043 maxResults: 10, 1044 showOnFocus: false 1045}); 1046map.addControl(searchLayer);
1047document.getElementsByClassName('search-layer')[0].getElementsByTagName('button')[0].className += ' fa fa-binoculars'; 1048document.getElementsByClassName('search-layer-input-search')[0].placeholder = 'Search feature ...'; 1049 1050 1051//scalebar 1052 1053 1054//layerswitcher 1055 1056var layerSwitcher = new ol.control.LayerSwitcher({ 1057 activationMode: 'click', 1058 startActive: true, 1059 tipLabel: "Layers", 1060 target: 'top-right-container', 1061 collapseLabel: '»', 1062 collapseTipLabel: 'Close' 1063 }); 1064map.addControl(layerSwitcher); 1065if (hasTouchScreen || isSmallScreen) { 1066 document.addEventListener('DOMContentLoaded', function() { 1067 setTimeout(function() { 1068 layerSwitcher.hidePanel(); 1069 }, 500); 1070 }); 1071} 1072 1073 1074 1075 1076 1077 1078//attribution 1079var bottomAttribution = new ol.control.Attribution({ 1080 collapsible: false, 1081 collapsed: false, 1082 className: 'bottom-attribution' 1083}); 1084map.addControl(bottomAttribution); 1085 1086map.once('rendercomplete', function() { 1087 var bottomAttributionUl = bottomAttribution.element.querySelector('ul'); 1088 if (bottomAttributionUl) { 1089 var layerAttrs = Array.from(bottomAttributionUl.querySelectorAll('li')) 1090 .map(function(li) { return li.innerHTML.trim(); }).filter(Boolean); 1091 var attribHtml = ` 1092 <a href="https://github.com/qgis2web/qgis2web">qgis2web</a> · 1093 <a href="https://openlayers.org/">OpenLayers</a> · 1094 <a href="https://qgis.org/">QGIS</a>`; 1095 if (layerAttrs.length > 0) { attribHtml += ' | ' + layerAttrs.join(', '); } 1096 bottomAttributionUl.innerHTML = '<li>' + attribHtml + '</li>'; 1097 } 1098}); 1099 1100 1101// Disable "popup on hover" or "highlight on hover" if ol-control mouseover 1102var preDoHover = doHover; 1103var preDoHighlight = doHighlight; 1104var isPopupAllActive = false; 1105document.addEventListener('DOMContentLoaded', function() { 1106 if (doHover || doHighlight) { 1107 var controlElements = document.getElementsByClassName('ol-control'); 1108 for (var i = 0; i < controlElements.length; i++) { 1109 controlElements[i].addEventListener('mouseover', function() { 1110 doHover = false; 1111 doHighlight = false; 1112 }); 1113 controlElements[i].addEventListener('mouseout', function() { 1114 doHover = preDoHover; 1115 if (isPopupAllActive) { return } 1116 doHighlight = preDoHighlight; 1117 }); 1118 } 1119 } 1120}); 1121 1122 1123//move controls inside containers, in order 1124 //zoom 1125 var zoomControl = document.getElementsByClassName('ol-zoom')[0]; 1126 if (zoomControl) { 1127 topLeftContainerDiv.appendChild(zoomControl); 1128 } 1129 //geolocate 1130 if (typeof geolocateControl !== 'undefined') { 1131 topLeftContainerDiv.appendChild(geolocateControl); 1132 } 1133 //measure 1134 if (typeof measureControl !== 'undefined') { 1135 topLeftContainerDiv.appendChild(measureControl); 1136 } 1137 //geocoder 1138 var searchbar = document.getElementsByClassName('photon-geocoder-autocomplete ol-unselectable ol-control')[0]; 1139 if (searchbar) { 1140 topLeftContainerDiv.appendChild(searchbar); 1141 } 1142 //search layer 1143 var searchLayerControl = document.getElementsByClassName('search-layer')[0]; 1144 if (searchLayerControl) { 1145 topLeftContainerDiv.appendChild(searchLayerControl); 1146 } 1147 //scale line 1148 var scaleLineControl = document.getElementsByClassName('ol-scale-line')[0]; 1149 if (scaleLineControl) { 1150 scaleLineControl.className += ' ol-control'; 1151 bottomLeftContainerDiv.appendChild(scaleLineControl); 1152 } 1153 //attribution 1154 var attributionControl = document.getElementsByClassName('bottom-attribution')[0]; 1155 if (attributionControl) { 1156 bottomRightContainerDiv.appendChild(attributionControl); 1157 }
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.