Feature/clustering market (#2050)
* Add support clustering and creating setting schema from google and tencent * Add settings for leaflet * Fix name setting * Fix text setting and change zoom level
This commit is contained in:
parent
45059ae660
commit
25e36583f8
357
ui/package-lock.json
generated
357
ui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -65,6 +65,7 @@
|
||||
"leaflet": "^1.5.1",
|
||||
"leaflet-polylinedecorator": "^1.6.0",
|
||||
"leaflet-providers": "^1.8.0",
|
||||
"leaflet.markercluster": "^1.4.1",
|
||||
"material-steppers": "git://github.com/thingsboard/material-steppers.git#master",
|
||||
"material-ui": "^0.16.1",
|
||||
"material-ui-number-input": "^5.0.16",
|
||||
|
||||
@ -19,7 +19,7 @@ var gmGlobals = {
|
||||
}
|
||||
|
||||
export default class TbGoogleMap {
|
||||
constructor($containerElement, utils, initCallback, defaultZoomLevel, dontFitMapBounds, disableScrollZooming, minZoomLevel, gmApiKey, gmDefaultMapType, defaultCenterPosition) {
|
||||
constructor($containerElement, utils, initCallback, defaultZoomLevel, dontFitMapBounds, disableScrollZooming, minZoomLevel, gmApiKey, gmDefaultMapType, defaultCenterPosition, markerClusteringSetting) {
|
||||
|
||||
var tbMap = this;
|
||||
this.utils = utils;
|
||||
@ -29,6 +29,7 @@ export default class TbGoogleMap {
|
||||
this.tooltips = [];
|
||||
this.defaultMapType = gmDefaultMapType;
|
||||
this.defaultCenterPosition = defaultCenterPosition;
|
||||
this.isMarketCluster = markerClusteringSetting.isMarketCluster;
|
||||
|
||||
function clearGlobalId() {
|
||||
if (gmGlobals.loadingGmId && gmGlobals.loadingGmId === tbMap.mapId) {
|
||||
@ -49,6 +50,10 @@ export default class TbGoogleMap {
|
||||
zoom: tbMap.defaultZoomLevel || 8,
|
||||
center: new google.maps.LatLng(tbMap.defaultCenterPosition[0], tbMap.defaultCenterPosition[1]) // eslint-disable-line no-undef
|
||||
});
|
||||
if (tbMap.isMarketCluster){
|
||||
tbMap.markersCluster = new MarkerClusterer(tbMap.map, [], // eslint-disable-line no-undef
|
||||
angular.merge({imagePath: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m'}, markerClusteringSetting));
|
||||
}
|
||||
if (initCallback) {
|
||||
initCallback();
|
||||
}
|
||||
@ -87,7 +92,10 @@ export default class TbGoogleMap {
|
||||
this.initMapFunctionName = 'initGoogleMap_' + this.mapId;
|
||||
|
||||
window[this.initMapFunctionName] = function() { // eslint-disable-line no-undef, angular/window-service
|
||||
lazyLoad.load({ type: 'js', path: 'https://unpkg.com/@google/markerwithlabel@1.2.3/src/markerwithlabel.js' }).then( // eslint-disable-line no-undef
|
||||
lazyLoad.load([ // eslint-disable-line no-undef
|
||||
{ type: 'js', path: 'https://unpkg.com/@google/markerwithlabel@1.2.3/src/markerwithlabel.js' },
|
||||
{ type: 'js', path: 'https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/markerclusterer.js' }
|
||||
]).then(
|
||||
function success() {
|
||||
gmGlobals.gmApiKeys[tbMap.apiKey].loaded = true;
|
||||
initGoogleMap();
|
||||
@ -105,6 +113,7 @@ export default class TbGoogleMap {
|
||||
);
|
||||
|
||||
};
|
||||
/* eslint-enable no-undef */
|
||||
|
||||
if (this.apiKey && this.apiKey.length > 0) {
|
||||
if (gmGlobals.gmApiKeys[this.apiKey]) {
|
||||
@ -143,6 +152,10 @@ export default class TbGoogleMap {
|
||||
return angular.isDefined(this.map);
|
||||
}
|
||||
|
||||
getContainer() {
|
||||
return this.isMarketCluster ? this.markersCluster : this.map;
|
||||
}
|
||||
|
||||
/* eslint-disable no-undef */
|
||||
updateMarkerLabel(marker, settings) {
|
||||
marker.set('labelContent', '<div style="color: '+ settings.labelColor +';"><b>'+settings.labelText+'</b></div>');
|
||||
@ -240,7 +253,11 @@ export default class TbGoogleMap {
|
||||
if (settings.showLabel) {
|
||||
marker.set('labelAnchor', new google.maps.Point(100, iconInfo.size[1] + 20));
|
||||
}
|
||||
marker.setMap(gMap.map);
|
||||
if(gMap.isMarketCluster) {
|
||||
gMap.getContainer().addMarker(marker);
|
||||
} else {
|
||||
marker.setMap(gMap.getContainer());
|
||||
}
|
||||
});
|
||||
|
||||
if (settings.displayTooltip) {
|
||||
|
||||
@ -48,7 +48,7 @@ export default class TbMapWidgetV2 {
|
||||
};
|
||||
|
||||
if (settings.defaultZoomLevel) {
|
||||
if (settings.defaultZoomLevel > 0 && settings.defaultZoomLevel < 21) {
|
||||
if (settings.defaultZoomLevel >= 0 && settings.defaultZoomLevel < 21) {
|
||||
this.defaultZoomLevel = Math.floor(settings.defaultZoomLevel);
|
||||
}
|
||||
}
|
||||
@ -69,6 +69,46 @@ export default class TbMapWidgetV2 {
|
||||
|
||||
var minZoomLevel = this.drawRoutes ? 18 : 15;
|
||||
|
||||
let markerClusteringSetting = {
|
||||
isMarketCluster: false
|
||||
};
|
||||
|
||||
if (settings.useClusterMarkers === true){
|
||||
if (mapProvider === 'google-map' || mapProvider === 'tencent-map') {
|
||||
markerClusteringSetting = {
|
||||
isMarketCluster: true,
|
||||
zoomOnClick: settings.zoomOnClick,
|
||||
averageCenter: true
|
||||
};
|
||||
if(angular.isDefined(settings.maxZoom) && settings.maxZoom >= 0 && settings.maxZoom < 19){
|
||||
markerClusteringSetting.maxZoom = Math.floor(settings.maxZoom);
|
||||
}
|
||||
if(angular.isDefined(settings.gridSize) && settings.gridSize > 0){
|
||||
markerClusteringSetting.gridSize = Math.floor(settings.gridSize);
|
||||
}
|
||||
if(angular.isDefined(settings.minimumClusterSize) && settings.minimumClusterSize > 1){
|
||||
markerClusteringSetting.minimumClusterSize = Math.ceil(settings.minimumClusterSize);
|
||||
}
|
||||
} else if(mapProvider === 'openstreet-map' || mapProvider === 'here') {
|
||||
markerClusteringSetting = {
|
||||
isMarketCluster: true,
|
||||
zoomToBoundsOnClick: settings.zoomOnClick,
|
||||
showCoverageOnHover: settings.showCoverageOnHover,
|
||||
removeOutsideVisibleBounds: settings.removeOutsideVisibleBounds,
|
||||
animate: settings.animate,
|
||||
chunkedLoading: settings.chunkedLoading
|
||||
};
|
||||
if(angular.isDefined(settings.maxClusterRadius) && settings.maxClusterRadius > 0){
|
||||
markerClusteringSetting.maxClusterRadius = Math.floor(settings.maxClusterRadius);
|
||||
}
|
||||
if(angular.isDefined(settings.maxZoom) && settings.maxZoom >= 0 && settings.maxZoom < 19){
|
||||
markerClusteringSetting.disableClusteringAtZoom = Math.floor(settings.maxZoom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
var initCallback = function () {
|
||||
tbMap.update();
|
||||
@ -86,7 +126,7 @@ export default class TbMapWidgetV2 {
|
||||
|
||||
let openStreetMapProvider = {};
|
||||
if (mapProvider === 'google-map') {
|
||||
this.map = new TbGoogleMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, settings.disableScrollZooming, minZoomLevel, settings.gmApiKey, settings.gmDefaultMapType, settings.defaultCenterPosition);
|
||||
this.map = new TbGoogleMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, settings.disableScrollZooming, minZoomLevel, settings.gmApiKey, settings.gmDefaultMapType, settings.defaultCenterPosition, markerClusteringSetting);
|
||||
} else if (mapProvider === 'openstreet-map') {
|
||||
if (settings.useCustomProvider && settings.customProviderTileUrl) {
|
||||
openStreetMapProvider.name = settings.customProviderTileUrl;
|
||||
@ -94,10 +134,10 @@ export default class TbMapWidgetV2 {
|
||||
} else {
|
||||
openStreetMapProvider.name = settings.mapProvider;
|
||||
}
|
||||
this.map = new TbOpenStreetMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, settings.disableScrollZooming, minZoomLevel, openStreetMapProvider, null,settings.defaultCenterPosition);
|
||||
this.map = new TbOpenStreetMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, settings.disableScrollZooming, minZoomLevel, openStreetMapProvider, null,settings.defaultCenterPosition, markerClusteringSetting);
|
||||
} else if (mapProvider === 'here') {
|
||||
openStreetMapProvider.name = settings.mapProvider;
|
||||
this.map = new TbOpenStreetMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, settings.disableScrollZooming, minZoomLevel, openStreetMapProvider, settings.credentials, settings.defaultCenterPosition);
|
||||
this.map = new TbOpenStreetMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, settings.disableScrollZooming, minZoomLevel, openStreetMapProvider, settings.credentials, settings.defaultCenterPosition, markerClusteringSetting);
|
||||
} else if (mapProvider === 'image-map') {
|
||||
this.map = new TbImageMap(this.ctx, $element, this.utils, initCallback,
|
||||
settings.mapImageUrl,
|
||||
@ -107,7 +147,7 @@ export default class TbMapWidgetV2 {
|
||||
settings.imageUrlAttribute,
|
||||
settings.useDefaultCenterPosition ? settings.defaultCenterPosition: null);
|
||||
} else if (mapProvider === 'tencent-map') {
|
||||
this.map = new TbTencentMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, settings.disableScrollZooming, minZoomLevel, settings.tmApiKey, settings.tmDefaultMapType, settings.defaultCenterPosition);
|
||||
this.map = new TbTencentMap($element, this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, settings.disableScrollZooming, minZoomLevel, settings.tmApiKey, settings.tmDefaultMapType, settings.defaultCenterPosition, markerClusteringSetting);
|
||||
}
|
||||
|
||||
|
||||
@ -728,6 +768,24 @@ export default class TbMapWidgetV2 {
|
||||
"formIndex":schema.groupInfoes.length,
|
||||
"GroupTitle":"Route Map Settings"
|
||||
});
|
||||
} else if (mapProvider !== 'image-map'){
|
||||
angular.merge(schema.schema.properties, markerClusteringSettingsSchema.schema.properties);
|
||||
schema.schema.required = schema.schema.required.concat(markerClusteringSettingsSchema.schema.required);
|
||||
schema.form.push(markerClusteringSettingsSchema.form);
|
||||
if (mapProvider === 'google-map' || mapProvider === 'tencent-map') {
|
||||
angular.merge(schema.schema.properties, markerClusteringSettingsSchemaGoogle.schema.properties);
|
||||
schema.schema.required = schema.schema.required.concat(markerClusteringSettingsSchemaGoogle.schema.required);
|
||||
schema.form[schema.form.length -1] = schema.form[schema.form.length -1].concat(markerClusteringSettingsSchemaGoogle.form);
|
||||
}
|
||||
if (mapProvider === 'openstreet-map' || mapProvider === 'here') {
|
||||
angular.merge(schema.schema.properties, markerClusteringSettingsSchemaLeaflet.schema.properties);
|
||||
schema.schema.required = schema.schema.required.concat(markerClusteringSettingsSchemaLeaflet.schema.required);
|
||||
schema.form[schema.form.length -1] = schema.form[schema.form.length -1].concat(markerClusteringSettingsSchemaLeaflet.form);
|
||||
}
|
||||
schema.groupInfoes.push({
|
||||
"formIndex":schema.groupInfoes.length,
|
||||
"GroupTitle":"Markers Clustering Settings"
|
||||
});
|
||||
}
|
||||
return schema;
|
||||
}
|
||||
@ -975,7 +1033,7 @@ const commonMapSettingsSchema =
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"defaultZoomLevel": {
|
||||
"title": "Default map zoom level (1 - 20)",
|
||||
"title": "Default map zoom level (0 - 20)",
|
||||
"type": "number"
|
||||
},
|
||||
"useDefaultCenterPosition": {
|
||||
@ -1251,6 +1309,103 @@ const routeMapSettingsSchema =
|
||||
]
|
||||
};
|
||||
|
||||
const markerClusteringSettingsSchema =
|
||||
{
|
||||
"schema": {
|
||||
"title": "Markers Clustering Configuration",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"useClusterMarkers": {
|
||||
"title": "Use map markers clustering",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"zoomOnClick": {
|
||||
"title": "Zoom when clicking on a cluster",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"maxZoom": {
|
||||
"title": "The maximum zoom level when a marker can be part of a cluster (0 - 18)",
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
},
|
||||
"form": [
|
||||
"useClusterMarkers",
|
||||
"zoomOnClick",
|
||||
"maxZoom"
|
||||
]
|
||||
};
|
||||
|
||||
const markerClusteringSettingsSchemaGoogle =
|
||||
{
|
||||
"schema": {
|
||||
"title": "Marker Clustering Configuration Google",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"gridSize": {
|
||||
"title": "Maximum radius that a cluster will cover in pixels",
|
||||
"type": "number",
|
||||
"default": 60
|
||||
},
|
||||
"minimumClusterSize": {
|
||||
"title": "The minimum number of markers in a cluster",
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
},
|
||||
"form": [
|
||||
"gridSize",
|
||||
"minimumClusterSize"
|
||||
]
|
||||
};
|
||||
|
||||
const markerClusteringSettingsSchemaLeaflet =
|
||||
{
|
||||
"schema": {
|
||||
"title": "Markers Clustering Configuration Leaflet",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"showCoverageOnHover": {
|
||||
"title": "Show the bounds of markers when mouse over a cluster",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"animate": {
|
||||
"title": "Show animation on markers when zooming",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"maxClusterRadius": {
|
||||
"title": "Maximum radius that a cluster will cover in pixels",
|
||||
"type": "number",
|
||||
"default": 80
|
||||
},
|
||||
"chunkedLoading": {
|
||||
"title": "Use chunks for adding markers so that the page does not freeze",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"removeOutsideVisibleBounds": {
|
||||
"title": "Use lazy load for adding markers",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
},
|
||||
"form": [
|
||||
"showCoverageOnHover",
|
||||
"animate",
|
||||
"maxClusterRadius",
|
||||
"chunkedLoading",
|
||||
"removeOutsideVisibleBounds"
|
||||
]
|
||||
};
|
||||
|
||||
const imageMapSettingsSchema =
|
||||
{
|
||||
"schema": {
|
||||
|
||||
@ -14,18 +14,22 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import 'leaflet.markercluster/dist/MarkerCluster.css'
|
||||
import 'leaflet.markercluster/dist/MarkerCluster.Default.css'
|
||||
import * as L from 'leaflet';
|
||||
import 'leaflet-providers';
|
||||
import 'leaflet.markercluster/dist/leaflet.markercluster'
|
||||
|
||||
export default class TbOpenStreetMap {
|
||||
|
||||
constructor($containerElement, utils, initCallback, defaultZoomLevel, dontFitMapBounds, disableScrollZooming, minZoomLevel, mapProvider, credentials, defaultCenterPosition) {
|
||||
constructor($containerElement, utils, initCallback, defaultZoomLevel, dontFitMapBounds, disableScrollZooming, minZoomLevel, mapProvider, credentials, defaultCenterPosition, markerClusteringSetting) {
|
||||
|
||||
this.utils = utils;
|
||||
this.defaultZoomLevel = defaultZoomLevel;
|
||||
this.dontFitMapBounds = dontFitMapBounds;
|
||||
this.minZoomLevel = minZoomLevel;
|
||||
this.tooltips = [];
|
||||
this.isMarketCluster = markerClusteringSetting.isMarketCluster;
|
||||
|
||||
if (!mapProvider) {
|
||||
mapProvider = {
|
||||
@ -48,6 +52,11 @@ export default class TbOpenStreetMap {
|
||||
var tileLayer = mapProvider.isCustom ? L.tileLayer(mapProvider.name) : L.tileLayer.provider(mapProvider.name, credentials);
|
||||
tileLayer.addTo(this.map);
|
||||
|
||||
if (this.isMarketCluster) {
|
||||
this.markersCluster = L.markerClusterGroup(markerClusteringSetting);
|
||||
this.map.addLayer(this.markersCluster);
|
||||
}
|
||||
|
||||
if (initCallback) {
|
||||
setTimeout(initCallback, 0); //eslint-disable-line
|
||||
}
|
||||
@ -58,6 +67,10 @@ export default class TbOpenStreetMap {
|
||||
return angular.isDefined(this.map);
|
||||
}
|
||||
|
||||
getContainer() {
|
||||
return this.isMarketCluster ? this.markersCluster : this.map;
|
||||
}
|
||||
|
||||
updateMarkerLabel(marker, settings) {
|
||||
marker.unbindTooltip();
|
||||
marker.bindTooltip('<div style="color: ' + settings.labelColor + ';"><b>' + settings.labelText + '</b></div>',
|
||||
@ -147,7 +160,7 @@ export default class TbOpenStreetMap {
|
||||
marker.bindTooltip('<div style="color: ' + settings.labelColor + ';"><b>' + settings.labelText + '</b></div>',
|
||||
{className: 'tb-marker-label', permanent: true, direction: 'top', offset: marker.tooltipOffset});
|
||||
}
|
||||
marker.addTo(opMap.map);
|
||||
marker.addTo(opMap.getContainer());
|
||||
});
|
||||
|
||||
if (settings.displayTooltip) {
|
||||
@ -162,7 +175,7 @@ export default class TbOpenStreetMap {
|
||||
}
|
||||
|
||||
removeMarker(marker) {
|
||||
this.map.removeLayer(marker);
|
||||
this.getContainer().removeLayer(marker);
|
||||
}
|
||||
|
||||
createTooltip(marker, dsIndex, settings, markerArgs) {
|
||||
|
||||
@ -19,7 +19,7 @@ var tmGlobals = {
|
||||
}
|
||||
|
||||
export default class TbTencentMap {
|
||||
constructor($containerElement, utils, initCallback, defaultZoomLevel, dontFitMapBounds, disableScrollZooming, minZoomLevel, tmApiKey, tmDefaultMapType, defaultCenterPosition) {
|
||||
constructor($containerElement, utils, initCallback, defaultZoomLevel, dontFitMapBounds, disableScrollZooming, minZoomLevel, tmApiKey, tmDefaultMapType, defaultCenterPosition, markerClusteringSetting) {
|
||||
var tbMap = this;
|
||||
this.utils = utils;
|
||||
this.defaultZoomLevel = defaultZoomLevel;
|
||||
@ -28,6 +28,7 @@ export default class TbTencentMap {
|
||||
this.tooltips = [];
|
||||
this.defaultMapType = tmDefaultMapType;
|
||||
this.defaultCenterPosition =defaultCenterPosition;
|
||||
this.isMarketCluster = markerClusteringSetting.isMarketCluster;
|
||||
|
||||
function clearGlobalId() {
|
||||
if (tmGlobals.loadingTmId && tmGlobals.loadingTmId === tbMap.mapId) {
|
||||
@ -49,6 +50,13 @@ export default class TbTencentMap {
|
||||
center: new qq.maps.LatLng(tbMap.defaultCenterPosition[0],tbMap.defaultCenterPosition[1]) // eslint-disable-line no-undef
|
||||
});
|
||||
|
||||
if (tbMap.isMarketCluster){
|
||||
tbMap.markersCluster = new qq.maps.MarkerCluster( // eslint-disable-line no-undef
|
||||
angular.merge({map:tbMap.map}, markerClusteringSetting)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if (initCallback) {
|
||||
initCallback();
|
||||
}
|
||||
@ -238,7 +246,11 @@ export default class TbTencentMap {
|
||||
var tMap = this;
|
||||
this.createMarkerIcon(marker, settings, (iconInfo) => {
|
||||
marker.setIcon(iconInfo.icon);
|
||||
if(tMap.isMarketCluster) {
|
||||
tMap.markersCluster.addMarker(marker);
|
||||
} else {
|
||||
marker.setMap(tMap.map);
|
||||
}
|
||||
if (settings.showLabel) {
|
||||
marker.label = new qq.maps.Label({
|
||||
clickable: false,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user