diff --git a/leaflet/markercluster.css b/leaflet/markercluster.css new file mode 100644 index 0000000..a4472c2 --- /dev/null +++ b/leaflet/markercluster.css @@ -0,0 +1 @@ +.leaflet-cluster-anim .leaflet-marker-icon,.leaflet-cluster-anim .leaflet-marker-shadow{-webkit-transition:-webkit-transform .3s ease-out,opacity .3s ease-in;-moz-transition:-moz-transform .3s ease-out,opacity .3s ease-in;-o-transition:-o-transform .3s ease-out,opacity .3s ease-in;transition:transform .3s ease-out,opacity .3s ease-in}.leaflet-cluster-spider-leg{-webkit-transition:-webkit-stroke-dashoffset .3s ease-out,-webkit-stroke-opacity .3s ease-in;-moz-transition:-moz-stroke-dashoffset .3s ease-out,-moz-stroke-opacity .3s ease-in;-o-transition:-o-stroke-dashoffset .3s ease-out,-o-stroke-opacity .3s ease-in;transition:stroke-dashoffset .3s ease-out,stroke-opacity .3s ease-in} \ No newline at end of file diff --git a/leaflet/markercluster.default.css b/leaflet/markercluster.default.css new file mode 100644 index 0000000..023610c --- /dev/null +++ b/leaflet/markercluster.default.css @@ -0,0 +1 @@ +.marker-cluster-small{background-color:rgba(181,226,140,.6)}.marker-cluster-small div{background-color:rgba(110,204,57,.6)}.marker-cluster-medium{background-color:rgba(241,211,87,.6)}.marker-cluster-medium div{background-color:rgba(240,194,12,.6)}.marker-cluster-large{background-color:rgba(253,156,115,.6)}.marker-cluster-large div{background-color:rgba(241,128,23,.6)}.leaflet-oldie .marker-cluster-small{background-color:#b5e28c}.leaflet-oldie .marker-cluster-small div{background-color:#6ecc39}.leaflet-oldie .marker-cluster-medium{background-color:#f1d357}.leaflet-oldie .marker-cluster-medium div{background-color:#f0c20c}.leaflet-oldie .marker-cluster-large{background-color:#fd9c73}.leaflet-oldie .marker-cluster-large div{background-color:#f18017}.marker-cluster{background-clip:padding-box;border-radius:20px}.marker-cluster div{width:30px;height:30px;margin-left:5px;margin-top:5px;text-align:center;border-radius:15px;font:12px "Helvetica Neue",Arial,Helvetica,sans-serif}.marker-cluster span{line-height:30px} \ No newline at end of file diff --git a/leaflet/markercluster.js b/leaflet/markercluster.js new file mode 100644 index 0000000..52e1735 --- /dev/null +++ b/leaflet/markercluster.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(((e=e||self).Leaflet=e.Leaflet||{},e.Leaflet.markercluster={}))}(this,function(e){"use strict";var t=L.MarkerClusterGroup=L.FeatureGroup.extend({options:{maxClusterRadius:80,iconCreateFunction:null,clusterPane:L.Marker.prototype.options.pane,spiderfyOnEveryZoom:!1,spiderfyOnMaxZoom:!0,showCoverageOnHover:!0,zoomToBoundsOnClick:!0,singleMarkerMode:!1,disableClusteringAtZoom:null,removeOutsideVisibleBounds:!0,animate:!0,animateAddingMarkers:!1,spiderfyShapePositions:null,spiderfyDistanceMultiplier:1,spiderLegPolylineOptions:{weight:1.5,color:"#222",opacity:.5},chunkedLoading:!1,chunkInterval:200,chunkDelay:50,chunkProgress:null,polygonOptions:{}},initialize:function(e){L.Util.setOptions(this,e),this.options.iconCreateFunction||(this.options.iconCreateFunction=this._defaultIconCreateFunction),this._featureGroup=L.featureGroup(),this._featureGroup.addEventParent(this),this._nonPointGroup=L.featureGroup(),this._nonPointGroup.addEventParent(this),this._inZoomAnimation=0,this._needsClustering=[],this._needsRemoving=[],this._currentShownBounds=null,this._queue=[],this._childMarkerEventHandlers={dragstart:this._childMarkerDragStart,move:this._childMarkerMoved,dragend:this._childMarkerDragEnd};e=L.DomUtil.TRANSITION&&this.options.animate;L.extend(this,e?this._withAnimation:this._noAnimation),this._markerCluster=e?L.MarkerCluster:L.MarkerClusterNonAnimated},addLayer:function(e){if(e instanceof L.LayerGroup)return this.addLayers([e]);if(!e.getLatLng)return this._nonPointGroup.addLayer(e),this.fire("layeradd",{layer:e}),this;if(!this._map)return this._needsClustering.push(e),this.fire("layeradd",{layer:e}),this;if(this.hasLayer(e))return this;this._unspiderfy&&this._unspiderfy(),this._addLayer(e,this._maxZoom),this.fire("layeradd",{layer:e}),this._topClusterLevel._recalculateBounds(),this._refreshClustersIcons();var t=e,i=this._zoom;if(e.__parent)for(;t.__parent._zoom>=i;)t=t.__parent;return this._currentShownBounds.contains(t.getLatLng())&&(this.options.animateAddingMarkers?this._animationAddLayer(e,t):this._animationAddLayerNonAnimated(e,t)),this},removeLayer:function(e){return e instanceof L.LayerGroup?this.removeLayers([e]):(e.getLatLng?this._map?e.__parent&&(this._unspiderfy&&(this._unspiderfy(),this._unspiderfyLayer(e)),this._removeLayer(e,!0),this.fire("layerremove",{layer:e}),this._topClusterLevel._recalculateBounds(),this._refreshClustersIcons(),e.off(this._childMarkerEventHandlers,this),this._featureGroup.hasLayer(e)&&(this._featureGroup.removeLayer(e),e.clusterShow&&e.clusterShow())):(!this._arraySplice(this._needsClustering,e)&&this.hasLayer(e)&&this._needsRemoving.push({layer:e,latlng:e._latlng}),this.fire("layerremove",{layer:e})):(this._nonPointGroup.removeLayer(e),this.fire("layerremove",{layer:e})),this)},addLayers:function(i,r){if(!L.Util.isArray(i))return this.addLayer(i);var n,s=this._featureGroup,o=this._nonPointGroup,a=this.options.chunkedLoading,h=this.options.chunkInterval,l=this.options.chunkProgress,u=i.length,_=0,d=!0;if(this._map){var p=(new Date).getTime(),c=L.bind(function(){var e=(new Date).getTime();for(this._map&&this._unspiderfy&&this._unspiderfy();_"+t+"",className:"marker-cluster"+e,iconSize:new L.Point(40,40)})},_bindEvents:function(){var e=this._map,t=this.options.spiderfyOnMaxZoom,i=this.options.showCoverageOnHover,r=this.options.zoomToBoundsOnClick,n=this.options.spiderfyOnEveryZoom;(t||r||n)&&this.on("clusterclick clusterkeypress",this._zoomOrSpiderfy,this),i&&(this.on("clustermouseover",this._showCoverage,this),this.on("clustermouseout",this._hideCoverage,this),e.on("zoomend",this._hideCoverage,this))},_zoomOrSpiderfy:function(e){var t=e.layer,i=t;if("clusterkeypress"!==e.type||!e.originalEvent||13===e.originalEvent.keyCode){for(;1===i._childClusters.length;)i=i._childClusters[0];i._zoom===this._maxZoom&&i._childCount===t._childCount&&this.options.spiderfyOnMaxZoom?t.spiderfy():this.options.zoomToBoundsOnClick&&t.zoomToBounds(),this.options.spiderfyOnEveryZoom&&t.spiderfy(),e.originalEvent&&13===e.originalEvent.keyCode&&this._map._container.focus()}},_showCoverage:function(e){var t=this._map;this._inZoomAnimation||(this._shownPolygon&&t.removeLayer(this._shownPolygon),2a._zoom;u--)l=new this._markerCluster(this,u,l),i[u].addObject(l,this._map.project(o.getLatLng(),u));return a._addChild(l),void this._removeFromGridUnclustered(o,t)}r[t].addObject(e,s)}this._topClusterLevel._addChild(e),e.__parent=this._topClusterLevel},_refreshClustersIcons:function(){this._featureGroup.eachLayer(function(e){e instanceof L.MarkerCluster&&e._iconNeedsUpdate&&e._updateIcon()})},_enqueue:function(e){this._queue.push(e),this._queueTimeout||(this._queueTimeout=setTimeout(L.bind(this._processQueue,this),300))},_processQueue:function(){for(var e=0;ee?(this._animationStart(),this._animationZoomOut(this._zoom,e)):this._moveEnd()},_getExpandedVisibleBounds:function(){return this.options.removeOutsideVisibleBounds?L.Browser.mobile?this._checkBoundsMaxLat(this._map.getBounds()):this._checkBoundsMaxLat(this._map.getBounds().pad(1)):this._mapBoundsInfinite},_checkBoundsMaxLat:function(e){var t=this._maxLat;return void 0!==t&&(e.getNorth()>=t&&(e._northEast.lat=1/0),e.getSouth()<=-t&&(e._southWest.lat=-1/0)),e},_animationAddLayerNonAnimated:function(e,t){t===e?this._featureGroup.addLayer(e):2===t._childCount?(t._addToMap(),e=t.getAllChildMarkers(),this._featureGroup.removeLayer(e[0]),this._featureGroup.removeLayer(e[1])):t._updateIcon()},_extractNonGroupLayers:function(e,t){var i,r=e.getLayers(),n=0;for(t=t||[];ni)&&(i=(o=d).lat),(!1===r||d.latn)&&(n=(h=d).lng),(!1===s||d.lng=this._circleSpiralSwitchover?this._generatePointsSpiral(e.length,t):(t.y+=10,this._generatePointsCircle(e.length,t)),this._animationSpiderfy(e,t))},unspiderfy:function(e){this._group._inZoomAnimation||(this._animationUnspiderfy(e),this._group._spiderfied=null)},_generatePointsCircle:function(e,t){var i,r,n=this._group.options.spiderfyDistanceMultiplier*this._circleFootSeparation*(2+e)/this._2PI,s=this._2PI/e,o=[],n=Math.max(n,35);for(o.length=e,i=0;i *:first-child { #map { height: 400px; } +#map * { + max-width: unset; +} #announcement { padding: 5px; @@ -244,25 +247,21 @@ details summary > *:first-child { --primary: #000; color: #000; } - body { font-family: serif; max-width: inherit; } - nav, -.actions, -#tts, -#interactions, -#tor, -#announcement { + .actions, + #tts, + #interactions, + #tor, + #announcement { display: none; } - a { text-decoration: none; } - .e-content a[href]:after { content: " [" attr(href) "]"; } diff --git a/templates/assets/js/geomap.js b/templates/assets/js/geomap.js index 62a274d..ee92a03 100644 --- a/templates/assets/js/geomap.js +++ b/templates/assets/js/geomap.js @@ -46,17 +46,17 @@ }).addTo(map) // Load map features + let cluster = L.markerClusterGroup().addTo(map) - let features = [] function fitFeatures() { // Make the map fit the features - map.fitBounds(L.featureGroup(features).getBounds(), { padding: [5, 5] }) + map.fitBounds(cluster.getBounds(), { padding: [5, 5] }) } // Map page getMapJson(mapEl.dataset.locations, locations => { locations.forEach(loc => { - features.push(L.marker([loc.Lat, loc.Lon]).addTo(map).on('click', function () { + cluster.addLayer(L.marker([loc.Lat, loc.Lon]).on('click', function () { window.open(loc.Post, '_blank').focus() })) }) @@ -66,12 +66,12 @@ tracks.forEach(track => { track.Paths.forEach(path => { // Use random color on map page for paths to better differentiate - features.push(L.polyline(path.map(point => [point.Lat, point.Lon]), { color: randomColor() }).addTo(map).on('click', function () { + cluster.addLayer(L.polyline(path.map(point => [point.Lat, point.Lon]), { color: randomColor() }).on('click', function () { window.open(track.Post, '_blank').focus() })) }) track.Points.forEach(point => { - features.push(L.marker([point.Lat, point.Lon]).addTo(map).on('click', function () { + cluster.addLayer(L.marker([point.Lat, point.Lon]).on('click', function () { window.open(track.Post, '_blank').focus() })) }) @@ -81,13 +81,13 @@ // Post map getMapJson(mapEl.dataset.paths, paths => { paths.forEach(path => { - features.push(L.polyline(path.map(point => [point.Lat, point.Lon]), { color: 'blue' }).addTo(map)) + cluster.addLayer(L.polyline(path.map(point => [point.Lat, point.Lon]), { color: 'blue' })) }) fitFeatures() }) getMapJson(mapEl.dataset.points, points => { points.forEach(point => { - features.push(L.marker([point.Lat, point.Lon]).addTo(map)) + cluster.addLayer(L.marker([point.Lat, point.Lon])) }) fitFeatures() }) @@ -102,9 +102,26 @@ css.href = '/-/leaflet/leaflet.css?v=1.9.4' document.head.appendChild(css) + // Marker Cluster plugin + let pluginCss1 = document.createElement('link') + pluginCss1.rel = 'stylesheet' + pluginCss1.href = '/-/leaflet/markercluster.css?v=1.5.3' + document.head.appendChild(pluginCss1) + + let pluginCss2 = document.createElement('link') + pluginCss2.rel = 'stylesheet' + pluginCss2.href = '/-/leaflet/markercluster.default.css?v=1.5.3' + document.head.appendChild(pluginCss2) + // JS let script = document.createElement('script') script.src = '/-/leaflet/leaflet.js?v=1.9.4' - script.onload = loadMap + script.onload = function () { + // Marker Cluster plugin + let plugin = document.createElement('script') + plugin.src = '/-/leaflet/markercluster.js?v=1.5.3' + plugin.onload = loadMap + document.head.appendChild(plugin) + } document.head.appendChild(script) })() \ No newline at end of file