From 5d1ccb1d54ff18b2609a5b5476f576bcd42ad4a3 Mon Sep 17 00:00:00 2001 From: David Molineus Date: Wed, 21 Jan 2015 14:24:22 +0100 Subject: [PATCH] Implement marker cluster. --- assets/maps/contao-leaflet.js | 2 +- assets/maps/src/Contao.js | 4 +- module/assets/img/cluster.png | Bin 0 -> 738 bytes module/assets/img/cluster_1.png | Bin 0 -> 647 bytes module/config/config.php | 6 + module/dca/tl_leaflet_layer.php | 166 ++++++++++++++++-- module/languages/en/tl_leaflet_layer.php | 76 +++++--- .../Mapper/Layer/MarkerClusterLayerMapper.php | 113 ++++++++++++ 8 files changed, 320 insertions(+), 47 deletions(-) create mode 100644 module/assets/img/cluster.png create mode 100644 module/assets/img/cluster_1.png create mode 100644 src/Netzmacht/Contao/Leaflet/Mapper/Layer/MarkerClusterLayerMapper.php diff --git a/assets/maps/contao-leaflet.js b/assets/maps/contao-leaflet.js index 7dea8b5..652a519 100644 --- a/assets/maps/contao-leaflet.js +++ b/assets/maps/contao-leaflet.js @@ -1 +1 @@ -L.Contao=L.Class.extend({includes:L.Mixin.Events,attribution:' | netzmacht creative',maps:{},icons:{},initialize:function(){L.Icon.Default.imagePath="assets/leaflet/libs/leaflet/images",this.setGeoJsonListeners(L.GeoJSON)},addMap:function(t,e){return e.map.attributionControl.setPrefix(e.map.attributionControl.options.prefix+this.attribution),this.maps[t]=e,this.fire("map:added",{id:t,map:e}),this},getMap:function(t){return"undefined"==typeof this.maps[t]?null:this.maps[t]},addIcon:function(t,e){return this.icons[t]=e,this.fire("icon:added",{id:t,icon:e}),this},loadIcons:function(t){for(var e=0;ei&&(n[n.length]=[e,t].join("=")),document.location.pathname+n.join("&")}}),L.contao=new L.Contao,L.Map.include({_dynamicBounds:null,calculateFeatureBounds:function(t,e){if(t){if(!this.options.adjustBounds&&!e)return;this._scanForBounds(t)}else this.eachLayer(this._scanForBounds,this);this._dynamicBounds&&this.fitBounds(this._dynamicBounds)},_scanForBounds:function(t){var e;t.feature&&t.feature.properties&&t.feature.properties.affectBounds?t.getBounds?(e=t.getBounds(),e.isValid()&&(this._dynamicBounds?this._dynamicBounds.extend(e):this._dynamicBounds=L.latLngBounds(e.getSouthWest(),e.getNorthEast()))):t.getLatLng&&(e=t.getLatLng(),this._dynamicBounds?this._dynamicBounds.extend(e):this._dynamicBounds=L.latLngBounds(e,e)):t.eachLayer&&t.eachLayer(this._scanForBounds,this)}}); \ No newline at end of file +L.Contao=L.Class.extend({includes:L.Mixin.Events,attribution:' | netzmacht creative',maps:{},icons:{},initialize:function(){L.Icon.Default.imagePath="assets/leaflet/libs/leaflet/images",this.setGeoJsonListeners(L.GeoJSON)},addMap:function(t,e){return e.map.attributionControl.setPrefix(e.map.attributionControl.options.prefix+this.attribution),this.maps[t]=e,this.fire("map:added",{id:t,map:e}),this},getMap:function(t){return"undefined"==typeof this.maps[t]?null:this.maps[t]},addIcon:function(t,e){return this.icons[t]=e,this.fire("icon:added",{id:t,icon:e}),this},loadIcons:function(t){for(var e=0;ei&&(n[n.length]=[e,t].join("=")),document.location.pathname+n.join("&")}}),L.contao=new L.Contao,L.Map.include({_dynamicBounds:null,calculateFeatureBounds:function(t,e){if(t){if(!this.options.adjustBounds&&!e)return;this._scanForBounds(t)}else this.eachLayer(this._scanForBounds,this);this._dynamicBounds&&this.fitBounds(this._dynamicBounds)},_scanForBounds:function(t){var e;t.feature&&t.feature.properties&&t.feature.properties.affectBounds?t.getBounds?(e=t.getBounds(),e.isValid()&&(this._dynamicBounds?this._dynamicBounds.extend(e):this._dynamicBounds=L.latLngBounds(e.getSouthWest(),e.getNorthEast()))):t.getLatLng&&(e=t.getLatLng(),this._dynamicBounds?this._dynamicBounds.extend(e):this._dynamicBounds=L.latLngBounds(e,e)):t.eachLayer&&t.eachLayer(this._scanForBounds,this)}}); \ No newline at end of file diff --git a/assets/maps/src/Contao.js b/assets/maps/src/Contao.js index c7c9253..3fc588f 100644 --- a/assets/maps/src/Contao.js +++ b/assets/maps/src/Contao.js @@ -119,8 +119,8 @@ L.Contao = L.Class.extend({ * @param map Pass a map object so that the data loading events are passed to the map. */ load: function (hash, type, options, customLayer, map) { - var url = this.createRequestUrl(hash); - var layer = omnivore[type](url, options, customLayer); + var url = this.createRequestUrl(hash), + layer = omnivore[type](url, options, customLayer); if (map) { // Required because Control.Loading tries to get _leafet_id which is created here. diff --git a/module/assets/img/cluster.png b/module/assets/img/cluster.png new file mode 100644 index 0000000000000000000000000000000000000000..832a1da1bec945469cef1eb34bd0aeb4df3e7f98 GIT binary patch literal 738 zcmV<80v-K{P)YCUFelB7bRzpU1w|sV zy93dkeFnq|8HWO)$io z4BlM7U;5@Opq@Bz75n*nL_H69A-$Fv0;_2-08(|FJhA^K5>0n>K~i`+L2?&9<)J1F zI8_9&43F0CnoT8@iX{j*(gQ~U4rgGTB()jx#3FHM2-AZn;1WijaBGi@!(j@Q7XcIy zX%}{Ey!tYS3(r5Ht}24Lr7Zeew&TFoR#b004*HFd5+VptD0n)D83q~wWljh^qaX0# zWHZvFUW`sW^>7Sdx2%OA?QcxXpl{-{o`b6g8*sU~vDgDMDFn|Ek3=vvSHNuAM>6K1 zG8)C~&m5A~QS^;}#EXl^baYGqum(^=SCSDH$3i9x-?p%>Hin$c7_impMyh=mPCt2xaCrnPxhzJz_7x|Pp_lq`?eU0?>^0vSg8O`a*Mn-sdhG!$MJu*^hee-(f|Me literal 0 HcmV?d00001 diff --git a/module/assets/img/cluster_1.png b/module/assets/img/cluster_1.png new file mode 100644 index 0000000000000000000000000000000000000000..9bcea904cc4b7847563b0581462cad806372b168 GIT binary patch literal 647 zcmV;20(kw2P);M1&0u)I^ zK~y-)os+#vYe5u+zkSXaV;~yQ(kd6h6p3hI6>3|Y~Y;Z?(UA;+gqG-)M_>A_4=%ZFbv7%ay&mj6GajEe4bn`M-)XYEiEw^ z3^+bM2B6dFP_NfNLQV;SAYeQmBOi-+oC)#Z;DGb array + ( + 'children' => true, + 'icon' => 'system/modules/leaflet/assets/img/cluster.png', ) ); diff --git a/module/dca/tl_leaflet_layer.php b/module/dca/tl_leaflet_layer.php index f1cd297..f2f90a5 100644 --- a/module/dca/tl_leaflet_layer.php +++ b/module/dca/tl_leaflet_layer.php @@ -144,7 +144,6 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array 'active' => array('active'), ), 'markers extends default' => array( - '+title' => array('markerCluster'), '+expert' => array('pointToLayer'), '+active' => array('deferred') ), @@ -157,7 +156,24 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array ), 'reference extends default' => array( '+title' => array('reference', 'standalone') - ) + ), + 'markercluster extends default' => array( + 'config' => array( + 'showCoverageOnHover', + 'zoomToBoundsOnClick', + 'removeOutsideVisibleBounds', + 'animateAddingMarkers', + 'spiderfyOnMaxZoom', + 'disableClusteringAtZoom', + 'maxClusterRadius', + 'singleMarkerMode', + ), + '+expert' => array( + 'polygonOptions', + 'iconCreateFunction', + 'disableDefaultStyle' + ), + ), ), 'metasubselectpalettes' => array( @@ -169,6 +185,11 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array 'HERE' => array('tile_provider_key', 'tile_provider_code'), ), ), + + 'metasubpalettes' => array( + 'spiderfyOnMaxZoom' => array('spiderfyDistanceMultiplier') + ), + 'fields' => array ( 'id' => array @@ -278,22 +299,6 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array 'eval' => array('mandatory' => true, 'maxlength' => 255, 'tl_class' => 'w50'), 'sql' => "varchar(255) NOT NULL default ''" ), - 'markerCluster' => array - ( - 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['markerCluster'], - 'exclude' => true, - 'inputType' => 'select', - 'options_callback' => array('Netzmacht\Contao\Leaflet\Dca\Layer', 'getMarkerClusterLayers'), - 'reference' => &$GLOBALS['TL_LANG']['leaflet_layer'], - 'eval' => array( - 'mandatory' => false, - 'maxlength' => 255, - 'tl_class' => 'w50', - 'chosen' => true, - 'includeBlankOption' => true - ), - 'sql' => "varchar(255) NOT NULL default ''" - ), 'deferred' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['deferred'], @@ -370,5 +375,130 @@ $GLOBALS['TL_DCA']['tl_leaflet_layer'] = array ), 'sql' => "mediumtext NULL" ), + 'showCoverageOnHover' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['showCoverageOnHover'], + 'exclude' => true, + 'inputType' => 'checkbox', + 'default' => true, + 'eval' => array('tl_class' => 'w50', 'submitOnChange' => false, 'isBoolean' => true), + 'sql' => "char(1) NOT NULL default '1'" + ), + 'zoomToBoundsOnClick' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['zoomToBoundsOnClick'], + 'exclude' => true, + 'inputType' => 'checkbox', + 'default' => true, + 'eval' => array('tl_class' => 'w50', 'submitOnChange' => false, 'isBoolean' => true), + 'sql' => "char(1) NOT NULL default '1'" + ), + 'spiderfyOnMaxZoom' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['spiderfyOnMaxZoom'], + 'exclude' => true, + 'inputType' => 'checkbox', + 'default' => true, + 'eval' => array('tl_class' => 'w50 m12', 'submitOnChange' => true, 'isBoolean' => true), + 'sql' => "char(1) NOT NULL default '1'" + ), + 'removeOutsideVisibleBounds' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['removeOutsideVisibleBounds'], + 'exclude' => true, + 'inputType' => 'checkbox', + 'default' => true, + 'eval' => array('tl_class' => 'w50', 'submitOnChange' => false, 'isBoolean' => true), + 'sql' => "char(1) NOT NULL default '1'" + ), + 'animateAddingMarkers' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['animateAddingMarkers'], + 'exclude' => true, + 'inputType' => 'checkbox', + 'default' => false, + 'eval' => array('tl_class' => 'w50', 'submitOnChange' => false, 'isBoolean' => true), + 'sql' => "char(1) NOT NULL default ''" + ), + 'disableClusteringAtZoom' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['disableClusteringAtZoom'], + 'exclude' => true, + 'inputType' => 'select', + 'options_callback' => array('Netzmacht\Contao\Leaflet\Dca\Leaflet', 'getZoomLevels'), + 'default' => '', + 'eval' => array( + 'maxlength' => 4, + 'rgxp' => 'digit', + 'tl_class' => 'w50', + 'includeBlankOption' => true, + 'nullIfEmpty' => true + ), + 'sql' => "int(4) NULL" + ), + 'maxClusterRadius' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['maxClusterRadius'], + 'exclude' => true, + 'inputType' => 'text', + 'default' => null, + 'eval' => array('maxlength' => 5, 'rgxp' => 'digit', 'tl_class' => 'w50', 'nullIfEmpty' => true), + 'sql' => "int(5) NULL" + ), + 'singleMarkerMode' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['singleMarkerMode'], + 'exclude' => true, + 'inputType' => 'checkbox', + 'default' => false, + 'eval' => array('tl_class' => 'w50 m12', 'submitOnChange' => false, 'isBoolean' => true), + 'sql' => "char(1) NOT NULL default ''" + ), + 'polygonOptions' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['polygonOptions'], + 'exclude' => true, + 'inputType' => 'textarea', + 'eval' => array( + 'preserveTags' => true, + 'decodeEntities' => true, + 'allowHtml' => true, + 'rte' => 'ace|json', + 'tl_class' => 'clr' + ), + 'sql' => "mediumtext NULL" + ), + 'spiderfyDistanceMultiplier' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['spiderfyDistanceMultiplier'], + 'exclude' => true, + 'inputType' => 'text', + 'default' => null, + 'eval' => array('maxlength' => 5, 'rgxp' => 'digit', 'tl_class' => 'w50', 'nullIfEmpty' => true), + 'sql' => "int(5) NULL" + ), + 'iconCreateFunction' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['iconCreateFunction'], + 'exclude' => true, + 'inputType' => 'textarea', + 'eval' => array( + 'preserveTags' => true, + 'decodeEntities' => true, + 'allowHtml' => true, + 'rte' => 'ace|javascript', + 'tl_class' => 'clr' + ), + 'sql' => "mediumtext NULL" + ), + 'disableDefaultStyle' => array + ( + 'label' => &$GLOBALS['TL_LANG']['tl_leaflet_layer']['disableDefaultStyle'], + 'exclude' => true, + 'inputType' => 'checkbox', + 'default' => false, + 'eval' => array('tl_class' => 'w50', 'submitOnChange' => false, 'isBoolean' => true), + 'sql' => "char(1) NOT NULL default ''" + ), ) ); diff --git a/module/languages/en/tl_leaflet_layer.php b/module/languages/en/tl_leaflet_layer.php index 60b3a11..fe5cf52 100644 --- a/module/languages/en/tl_leaflet_layer.php +++ b/module/languages/en/tl_leaflet_layer.php @@ -26,32 +26,56 @@ $GLOBALS['TL_LANG']['tl_leaflet_layer']['show'][1] = 'Show layer ID %s details $GLOBALS['TL_LANG']['tl_leaflet_layer']['cut'][0] = 'Move layer'; $GLOBALS['TL_LANG']['tl_leaflet_layer']['cut'][1] = 'Move layer ID %s'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['title'][0] = 'Title'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['title'][1] = 'Title of the layer.'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['alias'][0] = 'Alias'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['alias'][1] = 'Alias of the layer.'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['type'][0] = 'Type'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['type'][1] = 'Choose the layer type.'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['tile_provider'][0] = 'Tile provider'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['tile_provider'][1] = 'Choose the layer type.'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['tile_provider_variant'][0] = 'Tile variant'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['tile_provider_variant'][1] = 'Tile variant style.'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['active'][0] = 'Activate layer'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['active'][1] = 'Activate layer on the map.'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['reference'][0] = 'Reference'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['reference'][1] = 'Choose the reference layer. Otherwise the same javscript object is used.'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['standalone'][0] = 'Standalone'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['standalone'][1] = 'Integrate reference as a copy of the referenced layer.'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['markerCluster'][0] = 'Marker cluster'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['markerCluster'][1] = 'Choose a marker cluster layer so that markers get clustered.'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['deferred'][0] = 'Deferred loading'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['deferred'][1] = 'Load data of the layer deferred using ajax.'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['groupType'][0] = 'Group type'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['groupType'][1] = 'Choose a layer group type.'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['onEachFeature'][0] = 'onEachFeature expression'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['onEachFeature'][1] = 'Use a custom onEachFeature expression. Can be a anonymous function or method reference. If defined the extension does not handle popup adding for you.'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['pointToLayer'][0] = 'pointToLayer expression'; -$GLOBALS['TL_LANG']['tl_leaflet_layer']['pointToLayer'][1] = 'Use a custom pointToLayer expression. Can be a anonymous function or method reference. If defined the extension does not handle popup or icon adding for you.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['title'][0] = 'Title'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['title'][1] = 'Title of the layer.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['alias'][0] = 'Alias'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['alias'][1] = 'Alias of the layer.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['type'][0] = 'Type'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['type'][1] = 'Choose the layer type.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['tile_provider'][0] = 'Tile provider'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['tile_provider'][1] = 'Choose the layer type.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['tile_provider_variant'][0] = 'Tile variant'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['tile_provider_variant'][1] = 'Tile variant style.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['active'][0] = 'Activate layer'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['active'][1] = 'Activate layer on the map.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['reference'][0] = 'Reference'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['reference'][1] = 'Choose the reference layer. Otherwise the same javscript object is used.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['standalone'][0] = 'Standalone'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['standalone'][1] = 'Integrate reference as a copy of the referenced layer.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['markerCluster'][0] = 'Marker cluster'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['markerCluster'][1] = 'Choose a marker cluster layer so that markers get clustered.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['deferred'][0] = 'Deferred loading'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['deferred'][1] = 'Load data of the layer deferred using ajax.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['groupType'][0] = 'Group type'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['groupType'][1] = 'Choose a layer group type.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['onEachFeature'][0] = 'onEachFeature expression'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['onEachFeature'][1] = 'Use a custom onEachFeature expression. Can be a anonymous function or method reference. If defined the extension does not handle popup adding for you.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['pointToLayer'][0] = 'pointToLayer expression'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['pointToLayer'][1] = 'Use a custom pointToLayer expression. Can be a anonymous function or method reference. If defined the extension does not handle popup or icon adding for you.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['showCoverageOnHover'][0] = 'Show coverage on hover'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['showCoverageOnHover'][1] = 'When you mouse over a cluster it shows the bounds of its markers.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['zoomToBoundsOnClick'][0] = 'Zoom to bounds on click'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['zoomToBoundsOnClick'][1] = 'When you click a cluster we zoom to its bounds.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['spiderfyOnMaxZoom'][0] = 'Spiderfy on max zoom'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['spiderfyOnMaxZoom'][1] = 'When you click a cluster at the bottom zoom level we spiderfy it so you can see all of its markers.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['removeOutsideVisibleBounds'][0] = 'Remove when outside of visible bounds'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['removeOutsideVisibleBounds'][1] = 'Clusters and markers too far from the viewport are removed from the map for performance.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['animateAddingMarkers'][0] = 'Animate adding markers'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['animateAddingMarkers'][1] = 'If set to true then adding individual markers to the MarkerClusterGroup after it has been added to the map will add the marker and animate it in to the cluster.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['disableClusteringAtZoom'][0] = 'Disable clustering at zoom level'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['disableClusteringAtZoom'][1] = 'If set, at this zoom level and below markers will not be clustered. This defaults to disabled. '; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['maxClusterRadius'][0] = 'Max cluster radius'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['maxClusterRadius'][1] = 'The maximum radius that a cluster will cover from the central marker (in pixels).'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['polygonOptions'][0] = 'Polygon options'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['polygonOptions'][1] = 'Options to pass when creating the L.Polygon(points, options) to show the bounds of a cluster.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['singleMarkerMode'][0] = 'Show cluster instead of marker'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['singleMarkerMode'][1] = 'If set to true, overrides the icon for all added markers to make them appear as a 1 size cluster.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['spiderfyDistanceMultiplier'][0] = 'Spiderfy distance multiplier'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['spiderfyDistanceMultiplier'][1] = 'Increase from 1 to increase the distance away from the center that spiderfied markers are placed. Use if you are using big marker icons.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['iconCreateFunction'][0] = 'Create cluster icon function'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['iconCreateFunction'][1] = 'Function used to create the cluster icon.'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['disableDefaultStyle'][0] = 'Disable default style'; +$GLOBALS['TL_LANG']['tl_leaflet_layer']['disableDefaultStyle'][1] = 'Do not load default marker cluster stylesheets.'; $GLOBALS['TL_LANG']['tl_leaflet_layer']['groupTypes']['layer'][0] = 'Layer group'; $GLOBALS['TL_LANG']['tl_leaflet_layer']['groupTypes']['layer'][1] = 'Basic layer group.
See http://leafletjs.com/reference.html#layergroup'; diff --git a/src/Netzmacht/Contao/Leaflet/Mapper/Layer/MarkerClusterLayerMapper.php b/src/Netzmacht/Contao/Leaflet/Mapper/Layer/MarkerClusterLayerMapper.php new file mode 100644 index 0000000..480a529 --- /dev/null +++ b/src/Netzmacht/Contao/Leaflet/Mapper/Layer/MarkerClusterLayerMapper.php @@ -0,0 +1,113 @@ + + * @copyright 2015 netzmacht creative David Molineus + * @license LGPL 3.0 + * @filesource + * + */ + +namespace Netzmacht\Contao\Leaflet\Mapper\Layer; + +use Netzmacht\Contao\Leaflet\Mapper\DefinitionMapper; +use Netzmacht\Contao\Leaflet\Model\LayerModel; +use Netzmacht\JavascriptBuilder\Type\AnonymousFunction; +use Netzmacht\JavascriptBuilder\Type\Expression; +use Netzmacht\LeafletPHP\Definition; +use Netzmacht\LeafletPHP\Definition\HasEvents; +use Netzmacht\LeafletPHP\Definition\Layer; +use Netzmacht\LeafletPHP\Definition\Type\LatLngBounds; +use Netzmacht\LeafletPHP\Plugins\MarkerCluster\MarkerClusterGroup; +use Netzmacht\LeafletPHP\Plugins\Omnivore\OmnivoreLayer; + +/** + * Class MarkerClusterLayerMapper maps the layer database model to the marker cluster definition. + * + * @package Netzmacht\Contao\Leaflet\Mapper\Layer + */ +class MarkerClusterLayerMapper extends AbstractLayerMapper +{ + /** + * Class of the definition being created. + * + * @var string + */ + protected static $definitionClass = 'Netzmacht\LeafletPHP\Plugins\MarkerCluster\MarkerClusterGroup'; + + /** + * Layer type. + * + * @var string + */ + protected static $type = 'markercluster'; + + /** + * {@inheritdoc} + */ + protected function initialize() + { + parent::initialize(); + + $this + ->addOptions('showCoverageOnHover', 'zoomToBoundsOnClick', 'spiderfyOnMaxZoom') + ->addOption('removeOutsideVisibleBounds') + ->addConditionalOption('maxClusterRadius') + ->addConditionalOption('singleMarkerMode') + ->addConditionalOption('animateAddingMarkers') + ->addConditionalOption('disableClusteringAtZoom') + ->addConditionalOption('spiderfyDistanceMultiplier'); + } + + /** + * {@inheritdoc} + * @SuppressWarnings(PHPMD.Superglobals) + */ + protected function build( + Definition $definition, + \Model $model, + DefinitionMapper $mapper, + LatLngBounds $bounds = null, + Definition $parent = null + ) { + parent::build($definition, $model, $mapper, $bounds, $parent); + + /** @var MarkerClusterGroup $definition */ + + if ($model->iconCreateFunction) { + $definition->setIconCreateFunction(new Expression($model->iconCreateFunction)); + } + + if ($model->polygonOptions) { + $definition->setPolygonOptions((array) json_decode($model->polygonOptions, true)); + } + + if (!$model->disableDefaultStyle) { + $GLOBALS['TL_CSS'][] = 'assets/leaflet/libs/leaflet-markercluster/MarkerCluster.Default.css||static'; + } + + $collection = LayerModel::findBy( + array('pid=?', 'active=1'), + array($model->id), + array('order' => 'sorting') + ); + + if ($collection) { + foreach ($collection as $layerModel) { + $layer = $mapper->handle($layerModel); + + if ($layer instanceof Layer) { + $definition->addLayer($layer); + + if ($layer instanceof OmnivoreLayer) { + $callback = new AnonymousFunction(); + $callback->addLine('layers.' . $definition->getId() . '.addLayers(this.getLayers())'); + + $layer->on('ready', $callback); + } + } + } + } + } +}