// osmutils.js // Lizenz CC BY-NC-SA 4.0 // Jürgen Berkemeier // www.j-berkemeier.de // Version 1.5 vom 4. 11. 2019 "use strict"; window.JB = window.JB || {}; ( function(verstring) { JB.Debug_Info("",verstring,false); if(!JB.debuginfo && typeof(console) != "undefined" && typeof(console.log) == "function" ) console.log(verstring); } )("osmutils.js 1.5 vom 4. 11. 2019"); JB.Map = function(makemap) { var dieses = this; var id = makemap.id; var mapcanvas = makemap.mapdiv; dieses.id = id; dieses.makemap = makemap; dieses.mapcanvas = mapcanvas; this.cluster_zoomhistory = []; // Map anlegen this.maptypes = {}; var baseLayers = {}, overlayLayers = {}, nr=0; var satellit = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { maxZoom: 21, attribution: 'Map data © Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community' }); this.maptypes.Satellit = [nr++, satellit]; baseLayers["Satellit"] = satellit; var osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 19, attribution: 'Map data © OpenStreetMap and contributors CC-BY-SA' }); this.maptypes.OSM = [nr++, osm]; baseLayers["OSM"] = osm; var osmde = L.tileLayer('https://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png', { maxZoom: 19, attribution: 'Map data © OpenStreetMap and contributors CC-BY-SA' }); this.maptypes.OSMDE = [nr++, osmde]; baseLayers["OSMDE"] = osmde; var opentopo = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', { maxZoom: 17, attribution: 'Kartendaten: © OpenStreetMap-Mitwirkende, SRTM | Kartendarstellung: © OpenTopoMap (CC-BY-SA)' }); this.maptypes.OPENTOPO = [nr++, opentopo]; baseLayers["Open Topo"] = opentopo; if(JB.GPX2GM.OSM_Cycle_Api_Key && JB.GPX2GM.OSM_Cycle_Api_Key.length>0) { var osmcycle = L.tileLayer('https://{s}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png?apikey='+JB.GPX2GM.OSM_Cycle_Api_Key, { maxZoom: 22, attribution: 'Map data © OpenCycleMap and contributors CC-BY-SA' }); this.maptypes.OSM_Cycle = [nr++, osmcycle]; baseLayers["Cycle"] = osmcycle; } if(JB.GPX2GM.OSM_Landscape_Api_Key && JB.GPX2GM.OSM_Landscape_Api_Key.length>0) { var osmlandscape = L.tileLayer('https://{s}.tile.thunderforest.com/landscape/{z}/{x}/{y}.png?apikey='+JB.GPX2GM.OSM_Landscape_Api_Key, { maxZoom: 22, attribution: 'Map data © OpenCycleMap and contributors CC-BY-SA' }); this.maptypes.OSM_Landscape = [nr++, osmlandscape]; baseLayers["Landscape"] = osmlandscape; } var grau = L.tileLayer(JB.GPX2GM.Path+"Icons/Grau256x256.png", { maxZoom: 22 }); this.maptypes.Keine_Karte = [nr++, grau]; baseLayers[JB.GPX2GM.strings[JB.GPX2GM.parameters.doclang].noMap] = grau; var opensea = L.tileLayer('https://tiles.openseamap.org/seamark/{z}/{x}/{y}.png', { attribution: 'Kartendaten: © OpenSeaMap contributors' }); this.maptypes.Open_Sea = [nr++, opensea]; overlayLayers["Open Sea"] = opensea; this.map = L.map(mapcanvas, { // layers: osm, closePopupOnClick: false, scrollWheelZoom: makemap.parameters.scrollwheelzoom, tap: false } ); if(makemap.parameters.unit=="si") L.control.scale({imperial:false}).addTo(this.map); // Mit Maßstab km else L.control.scale({metric:false}).addTo(this.map); // Mit Maßstab ml var ctrl_layer = null; JB.onresize(mapcanvas,function(w,h){ if(w>200 && h>190 && makemap.parameters.showmaptypecontroll) { if(!ctrl_layer) ctrl_layer = L.control.layers(baseLayers, overlayLayers).addTo(dieses.map); } else { if(ctrl_layer) { ctrl_layer.remove(); ctrl_layer = null; } } },true); // Mein Copyright und Versionshinweis L.Control.CP = L.Control.extend({ onAdd: function(map) { var jbcp = document.createElement('a'); jbcp.href='https://www.j-berkemeier.de/GPXViewer'; jbcp.innerHTML = "JB"; jbcp.style.color = "white"; jbcp.style.textDecoration = "none"; jbcp.style.margin = " 0 0 0 8px"; jbcp.style.fontSize = '10px'; jbcp.style.fontFamily = 'Arial, sans-serif'; jbcp.title = "GPX Viewer " + JB.GPX2GM.ver; return jbcp; }, onRemove: function(map) {} }); new L.Control.CP({ position: 'bottomleft' }).addTo(this.map); // Button für Full Screen / normale Größe if(makemap.parameters.fullscreenbutton) { var fsb = document.createElement("button"); fsb.style.backgroundColor = "transparent"; fsb.style.border = "none"; fsb.style.padding = "7px 7px 7px 0"; fsb.style.cursor = "pointer"; var fsbim = document.createElement("img"); fsbim.src = JB.GPX2GM.Path+"Icons/lupe_p_32.png"; //fsbim.width = "200px"; fsb.title = fsbim.title = fsbim.alt = JB.GPX2GM.strings[JB.GPX2GM.parameters.doclang].fullScreen; fsbim.large = false; var ele = mapcanvas.parentNode; fsb.onclick = function() { this.blur(); if(fsbim.large) { document.body.style.overflow = ""; fsbim.src = JB.GPX2GM.Path+"Icons/lupe_p_32.png"; fsb.title = fsbim.title = fsbim.alt = JB.GPX2GM.strings[JB.GPX2GM.parameters.doclang].fullScreen; ele.style.left = ele.oleft + "px"; ele.style.top = ele.otop + "px"; ele.style.width = ele.owidth + "px"; ele.style.height = ele.oheight + "px"; ele.style.margin = ele.omargin; ele.style.padding = ele.opadding; window.setTimeout(function() { JB.removeClass("JBfull",ele); ele.style.position = ele.sposition; ele.style.left = ele.sleft; ele.style.top = ele.stop; ele.style.width = ele.swidth; ele.style.height = ele.sheight; //ele.style.zIndex = ele.szindex; },1000); } else { document.body.style.overflow = "hidden"; fsbim.src = JB.GPX2GM.Path+"Icons/lupe_m_32.png"; fsb.title = fsbim.title = fsbim.alt = JB.GPX2GM.strings[JB.GPX2GM.parameters.doclang].normalSize; var scrollY = 0; if(document.documentElement.scrollTop && document.documentElement.scrollTop!=0) scrollY = document.documentElement.scrollTop; else if(document.body.scrollTop && document.body.scrollTop!=0) scrollY = document.body.scrollTop; else if(window.scrollY) scrollY = window.scrollY; else if(window.pageYOffset) scrollY = window.pageYOffset; var rect = JB.getRect(ele); ele.oleft = rect.left; ele.otop = rect.top - scrollY; ele.owidth = rect.width; ele.oheight = rect.height; //ele.szindex = ele.style.zIndex; ele.sposition = ele.style.position; ele.omargin = ele.style.margin; ele.opadding = ele.style.padding; ele.sleft = ele.style.left; ele.stop = ele.style.top; ele.swidth = ele.style.width; ele.sheight = ele.style.height; ele.style.position = "fixed"; ele.style.left = ele.oleft+"px"; ele.style.top = ele.otop+"px"; ele.style.width = ele.owidth+"px"; ele.style.height = ele.oheight+"px"; //ele.style.zIndex = "1001"; window.setTimeout(function() { JB.addClass("JBfull",ele); ele.style.width = "100%"; ele.style.height = "100%"; ele.style.left = "0px"; ele.style.top = "0px"; ele.style.margin = "0px"; ele.style.padding = "0px"; },100); } fsbim.large = !fsbim.large; }; fsb.appendChild(fsbim); fsb.index = 0; L.Control.Fsbutton = L.Control.extend({ onAdd: function(map) { return fsb; } }); var fsbutton = new L.Control.Fsbutton({ position: 'topright' }); fsbutton.addTo(this.map); } // fullscreenbutton // Button für Traffic-Layer if(makemap.parameters.trafficbutton) { console.warn("Traffic-Layer wird unter Leaflet (noch) nicht unterstützt."); } // Button für Anzeige aktuelle Position if(makemap.parameters.currentlocationbutton) { var clb = document.createElement("button"); clb.style.backgroundColor = "white"; clb.style.border = "none"; clb.style.width = "28px"; clb.style.height = "28px"; clb.style.margin = "10px 10px 0 0"; clb.style.borderRadius = "2px"; clb.style.cursor = "pointer"; clb.title = JB.GPX2GM.strings[JB.GPX2GM.parameters.doclang].showCurrentLocation; var clbimg = document.createElement("img"); clbimg.style.position = "absolute"; clbimg.style.top = "50%"; clbimg.style.left = "50%"; clbimg.style.transform = "translate(-50%, -50%)"; clbimg.src = JB.GPX2GM.Path+"Icons/whereami.svg"; var wpid = -1, marker = null, first; clb.onclick = function() { this.blur(); if (navigator.geolocation) { var geolocpos = function(position) { var lat = position.coords.latitude; var lon = position.coords.longitude; marker.setLatLng([lat,lon]); if(first) { dieses.map.setView([lat,lon]); first = false; } } var geolocerror = function(error) { var errorCodes = ["Permission Denied","Position unavailible","Timeout"]; var errorString = (error.code<=3)?errorCodes[error.code-1]:"Error code: "+error.code; JB.Debug_Info("Geolocation-Dienst fehlgeschlagen!",errorString+". "+error.message,true); } first = true; if(!marker) marker = dieses.Marker({lat:0,lon:0},JB.icons.CL)[0]; if ( wpid == -1 ) { clb.title = JB.GPX2GM.strings[JB.GPX2GM.parameters.doclang].hideCurrentLocation; wpid = navigator.geolocation.watchPosition(geolocpos,geolocerror,{enableHighAccuracy:true, timeout: 5000, maximumAge: 60000}); marker.addTo(dieses.map); JB.Debug_Info("","Geolocation-Dienst wird eingerichtet.",false); } else { clb.title = JB.GPX2GM.strings[JB.GPX2GM.parameters.doclang].showCurrentLocation; navigator.geolocation.clearWatch(wpid); wpid = -1; marker.remove(); JB.Debug_Info("","Geolocation-Dienst wird abgeschaltet.",false); } } else JB.Debug_Info("geolocation","Geolocation wird nicht unterstützt!",true); } // click-Handler clb.appendChild(clbimg); L.Control.Clbutton = L.Control.extend({ onAdd: function(map) { return clb; } }); var clbutton = new L.Control.Clbutton({ position: 'topright' }); clbutton.addTo(this.map); } // currentlocationbutton // Scalieren nach MAP-Resize dieses.zoomstatus = {}; dieses.zoomstatus.iszoomed = false; dieses.zoomstatus.zoom_changed = function() { dieses.zoomstatus.iszoomed = true; dieses.zoomstatus.level = dieses.map.getZoom(); dieses.zoomstatus.w = mapcanvas.offsetWidth; dieses.zoomstatus.h = mapcanvas.offsetHeight; } dieses.zoomstatus.move_end = function() { dieses.zoomstatus.iszoomed = true; dieses.mapcenter = dieses.map.getCenter(); } dieses.map.on("moveend", dieses.zoomstatus.move_end); JB.onresize(mapcanvas,function(w,h) { if(w*h==0) return; dieses.map.invalidateSize(); dieses.map.setView(dieses.mapcenter); dieses.map.off("zoomend", dieses.zoomstatus.zoom_changed); if(dieses.zoomstatus.iszoomed) { var dz = Math.round(Math.min(Math.log(w/dieses.zoomstatus.w)/Math.LN2,Math.log(h/dieses.zoomstatus.h)/Math.LN2)); dieses.map.setZoom(dieses.zoomstatus.level+dz); } else { if(dieses.bounds) { dieses.map.fitBounds(dieses.bounds,{padding:[20,20]}); dieses.map.setView(dieses.mapcenter); dieses.zoomstatus.level = dieses.map.getZoom(); dieses.zoomstatus.w = w; dieses.zoomstatus.h = h; } } }); } // JB.Map JB.Map.prototype.MapEvents = {id:-1, events:[]}; JB.Map.prototype.addMapEvent = function(event,fkt) { this.map.on(event,fkt); this.MapEvents.id ++; this.MapEvents.events[this.MapEvents.id] = {event: event, fkt: fkt} ; return this.MapEvents.id ++;; } // addMapEvent JB.Map.prototype.addMapEventOnce = function(event,fkt) { var oncefkt = function(ev) { fkt(ev); this.map.off(event,oncefkt); } this.map.on(event,oncefkt); this.MapEvents.id ++; this.MapEvents.events[this.MapEvents.id] = {event: event, fkt: oncefkt} ; return this.MapEvents.id ++;; } // addMapEventOnce JB.Map.prototype.removeEvent = function(eventid) { this.map.off(this.MapEvents.events[eventid].event, this.MapEvents.events[eventid].fkt); } // removeMapEvent JB.Map.prototype.getZoom = function() { return {zoom:this.map.getZoom(),maxzoom:this.map.getMaxZoom()}; } JB.Map.prototype.change = function(maptype) { var mt = "OSM"; if(maptype in this.maptypes) mt = maptype; if(maptype=="Open_Sea") mt = "OSM"; var nr = this.maptypes[mt][0]; var type = this.maptypes[mt][1]; for(var m in this.maptypes) this.map.removeLayer(this.maptypes[m][1]); if(this.makemap.parameters.showmaptypecontroll) { var layerControlElement = this.mapcanvas.getElementsByClassName('leaflet-control-layers')[0]; if(layerControlElement) { var openseacheckbox = layerControlElement.querySelectorAll('input[type=checkbox]')[0]; if(maptype=="Open_Sea") { if(!openseacheckbox.checked) openseacheckbox.click(); } else { if(openseacheckbox.checked) openseacheckbox.click(); } } } this.map.addLayer(type); JB.Debug_Info(this.id,"Maptype, gewählt: "+maptype+", eingestellt: "+mt,false); } // change JB.Map.prototype.getPixelPerKM = function(gpxdaten) { var bounds = this.map.getBounds(); if(bounds) { var latlon1 = bounds.getNorthEast(); var latlon2 = bounds.getSouthWest(); var korrfak = 1; } else { JB.Debug_Info(" getPixelPerKM","Bounds konnten nicht gelesen werden, nehme Min/Max-Werte aus GPX-Daten",false); var latlon1 = {lat: gpxdaten.latmax, lng: gpxdaten.lonmax}; var latlon2 = {lat: gpxdaten.latmin, lng: gpxdaten.lonmin}; var korrfak = 0.7; } JB.entf.init(latlon1.lat,latlon1.lng,0); var dist = JB.entf.rechne(latlon2.lat,latlon2.lng,0); JB.entf.init(latlon1.lat,latlon1.lng,0); var xdist = JB.entf.rechne(latlon1.lat,latlon2.lng,0); JB.entf.init(latlon1.lat,latlon1.lng,0); var ydist = JB.entf.rechne(latlon2.lat,latlon1.lng,0); var w = this.mapcanvas.offsetWidth; var h = this.mapcanvas.offsetHeight; var wh = Math.sqrt(w*w+h*h); var ppk = Math.min(w/xdist,h/ydist); ppk = Math.min(ppk,wh/dist); ppk *= korrfak; return ppk; } // getPixelPerKM JB.Map.prototype.rescale = function(gpxdaten) { var dieses = this; dieses.map.off("moveend", dieses.zoomstatus.move_end); dieses.map.off("zoomend", dieses.zoomstatus.zoom_changed); dieses.bounds = [[gpxdaten.latmin,gpxdaten.lonmin], [gpxdaten.latmax,gpxdaten.lonmax]]; this.map.fitBounds(dieses.bounds,{padding:[20,20]}); dieses.zoomstatus.iszoomed = false; dieses.mapcenter = dieses.map.getCenter(); dieses.zoomstatus.level = dieses.map.getZoom(); dieses.zoomstatus.w = dieses.mapcanvas.offsetWidth; dieses.zoomstatus.h = dieses.mapcanvas.offsetHeight; dieses.map.on("zoomend", dieses.zoomstatus.zoom_changed); dieses.map.on("moveend", dieses.zoomstatus.move_end); /* var zoom = dieses.getZoom(); // --------------------!!!!!!!!!!!!!!!!!!!!!---------------------!!!!!!!!!!!!!! console.log("rescale", zoom.zoom, zoom.maxzoom); if(zoom.zoom > zoom.maxzoom) { dieses.map.setZoom(zoom.maxzoom); dieses.zoomstatus.level = zoom.maxzoom; console.log("rescale", zoom.zoom, zoom.maxzoom); }*/ } // rescale JB.Map.prototype.infowindow = function(info,coord) { var popup = L.popup({maxWidth: this.map.getContainer().offsetWidth-200, autoClose: false }) .setLatLng(coord); if(typeof(info) == "string") popup.setContent("