Reputation: 1257
I am using Azure map Spider Cluster in this i am unable to change the style of markers group which is display on click of cluster bubble. I got the success in case of marker which is outside the cluster bubble with the help of HtmlMarkerLayer class but unable to change the style of markers inside cluster bubble. Below is my code:
<html lang="en">
<head>
<!-- Add references to the Azure Maps Map control JavaScript and CSS files. -->
<link href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.css" rel="stylesheet" />
<script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.js"></script>
<script src="https://raw.githubusercontent.com/Azure-Samples/azure-maps-html-marker-layer/main/dist/azure-maps-html-marker-layer.min.js"></script>
<script src="https://raw.githubusercontent.com/Azure-Samples/azure-maps-spider-clusters/main/dist/azure-maps-spider-clusters.min.js"></script>
<style>
.customInfobox { max-width: 240px; padding: 10px; font-size: 12px; margin-right: 20px; white-space: normal }
.customInfobox .name { font-size: 14px; font-weight: bold; margin-bottom: 5px }
.popup-content-container .popup-close { top: 12px !important; right: 6px !important; color: #ffffff !important; font-size: 16px !important; line-height: 18px !important; height: 15px !important; background: #000000 !important; width: 15px !important; border-radius: 50px !important; display: flex !important; justify-content: center !important; align-items: center !important; }
.atlas-map-canvas { width: 100% !important }
</style>
</head>
<body onload="GetMap()">
<div id="myMap" style="position:relative;width:100%;min-width:290px;height:600px;"></div>
<script>
var map, datasource, popup, spiderManager;
function GetMap() {
//Initialize a map instance.
map = new atlas.Map('myMap', {
center: [-110, 50],
zoom: 2,
view: 'Auto',
//Add authentication details for connecting to Azure Maps.
authOptions: {
//Use Azure Active Directory authentication.
authType: 'subscriptionKey',
subscriptionKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
}
});
var cordinates = [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [-84.28295, 30.46454] }, "properties": { "Name": "aa", "Status": "online" } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [-84.28295, 30.46454] }, "properties": { "Name": "bb", "Status": "offline" } },
{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [-54.28295, 60.46454] }, "properties": { "Name": "cc", "Status": "offline" } },
{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [-58.28295, 66.46454] }, "properties": { "Name": "dd", "Status": "online" } }];
var positions = { "type": "FeatureCollection", "features": cordinates };
map.setCamera({
//center map
bounds: atlas.data.BoundingBox.fromData(positions),
padding: 50
});
map.events.add('ready', function () {
//Create a popup.
popup = new atlas.Popup();
//Hide popup when user clicks or moves the map.
map.events.add('click', hidePopup);
map.events.add('movestart', hidePopup);
//Create a data source to add your data to.
datasource = new atlas.source.DataSource(null, {
//Tell the data source to cluster point data.
cluster: true,
//The radius in pixels to cluster points together.
// clusterRadius: 45,
clusterProperties: { //Calculate counts for each entity type in a cluster
'online': ['+', ['case', ['==', ['get', 'Status'], 'online'], 1, 0]],
'offline': ['+', ['case', ['==', ['get', 'Status'], 'offline'], 1, 0]]
},
//The maximium zoom level in which clustering occurs.
//If you zoom in more than this, all points are rendered as symbols.
clusterMaxZoom: 24,
maxZoom: 24
});
//set data to datasource
datasource.setShapes(positions)
map.sources.add(datasource);
//Create a layer for rendering clustered data in the data source.
var clusterBubbleLayer = new atlas.layer.BubbleLayer(datasource, null, {
//Scale the size of the clustered bubble based on the number of points inthe cluster.
radius: [
'step',
['get', 'point_count'],
20, //Default of 20 pixel radius.
100, 30, //If point_count >= 100, radius is 30 pixels.
750, 40 //If point_count >= 750, radius is 40 pixels.
],
//Change the color of the cluster based on the value on the point_cluster property of the cluster.
color: [
'case', //Use a conditional case expression.
// all offline
['>', ['get', 'offline'], 0] && ['==', ['get', 'online'], 0],
'#a5a5a5',
// all online
['>', ['get', 'online'], 0] && ['==', ['get', 'offline'], 0],
'#6aa84f',
// online and offline both
'#ff9900'
],
strokeWidth: 0,
filter: ['has', 'point_count'] //Only rendered data points which have a point_count property, which clusters do.
});
//Create a layer to render the individual locations.
var shapeLayer = new atlas.layer.SymbolLayer(datasource, null, {
filter: ['!', ['has', 'point_count']] //Filter out clustered points from this layer.
});
//Add the clusterBubbleLayer and two additional layers to the map.
map.layers.add([
clusterBubbleLayer,
//Create a symbol layer to render the count of locations in a cluster.
new atlas.layer.SymbolLayer(datasource, null, {
iconOptions: {
image: 'none', //Hide the icon image.
},
textOptions: {
textField: '{point_count_abbreviated}',
offset: [0, 0.4]
},
filter: ['!', ['has', 'point_count']]
}),
shapeLayer
]);
markerLayer = new atlas.layer.HtmlMarkerLayer(datasource, null, {
markerCallback: function (id, position, properties) {
//Check to see if marker represents a cluster.
if (properties.cluster) {
return new atlas.PieChartMarker({
position: position,
colors: '#ffffff',
fillColor: 'white',
strokeColor: 'white',
text: properties.point_count_abbreviated
});
} else {
//for single marker
return new atlas.HtmlMarker({
position: position,
color: properties.Status == 'online' ? '#4cae4c' : '#808080',
});
}
}
});
// map.events.add('click', markerLayer, markerClicked);
map.layers.add(markerLayer);
//Create an instance of the spider manager.
spiderManager = new atlas.SpiderClusterManager(map, clusterBubbleLayer, shapeLayer);
//Add event handler for when a feature is selected.
map.events.add('featureSelected', spiderManager, function (e) {
if (e.cluster) {
showPopup(e.cluster.geometry.coordinates, e.shape.getProperties(), [0, 0]);
} else {
showPopup(e.shape.getCoordinates(), e.shape.getProperties(), [0, -20]);
}
});
//Add event handler for when a feature is unselected.
map.events.add('featureUnselected', spiderManager, function () {
hidePopup();
});
});
}
var popupTemplate = '<div class="customInfobox"><div class="name">{name} ({status})</div></div>';
showPopup = function (position, properties, pixelOffset) {
var content = popupTemplate.replace(/{name}/g, properties.Name).replace(/{status}/g, properties.Status);
popup.setOptions({
//Update the content of the popup.
content: content,
//Update the position of the popup with the symbols coordinate.
position: position,
//Offset the popups position for better alignment with the layer.
pixelOffset: pixelOffset
});
//Open the popup.
popup.open(map);
}
hidePopup = function () {
popup.close();
}
</script>
</body>
</html>
For more explanation, please check below image:
Please help me to fix this. Thanks in advance.
Upvotes: 0
Views: 1159
Reputation: 17964
I wouldn't recommend using the HtmlMarker layer unless you need to use HTML DOM elements or CSS to style your marker, SymbolLayer is much faster.
If you customize how the shapeLayer
(Symbol layer) in your app renders the points, you will find that the spider manager automatically aligns with the same style when showing the expanded points.
I'm guessing you are using HtmlMarker layer as you wanted to specify custom colors for your markers, and want pie charts for the clusters. For symbol layers you use icons, but there is a built-in tool for generating these icons from built in templates (samples).
Here is a modified version of your code that hides the HtmlMarker for individual points, generates the green and grey marker icons, and uses the symbol layer to customize how your points appear on the map.
<html lang="en">
<head>
<!-- Add references to the Azure Maps Map control JavaScript and CSS files. -->
<link href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.css" rel="stylesheet" />
<script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.js"></script>
<script src="https://raw.githubusercontent.com/Azure-Samples/azure-maps-html-marker-layer/main/dist/azure-maps-html-marker-layer.min.js"></script>
<script src="https://raw.githubusercontent.com/Azure-Samples/azure-maps-spider-clusters/main/dist/azure-maps-spider-clusters.min.js"></script>
<style>
.customInfobox { max-width: 240px; padding: 10px; font-size: 12px; margin-right: 20px; white-space: normal }
.customInfobox .name { font-size: 14px; font-weight: bold; margin-bottom: 5px }
.popup-content-container .popup-close { top: 12px !important; right: 6px !important; color: #ffffff !important; font-size: 16px !important; line-height: 18px !important; height: 15px !important; background: #000000 !important; width: 15px !important; border-radius: 50px !important; display: flex !important; justify-content: center !important; align-items: center !important; }
.atlas-map-canvas { width: 100% !important }
</style>
</head>
<body onload="GetMap()">
<div id="myMap" style="position:relative;width:100%;min-width:290px;height:600px;"></div>
<script>
var map, datasource, popup, spiderManager;
function GetMap() {
//Initialize a map instance.
map = new atlas.Map('myMap', {
center: [-110, 50],
zoom: 2,
view: 'Auto',
//Add authentication details for connecting to Azure Maps.
authOptions: {
//Use Azure Active Directory authentication.
authType: 'subscriptionKey',
subscriptionKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
}
});
var cordinates = [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [-84.28295, 30.46454] }, "properties": { "Name": "aa", "Status": "online" } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [-84.28295, 30.46454] }, "properties": { "Name": "bb", "Status": "offline" } },
{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [-54.28295, 60.46454] }, "properties": { "Name": "cc", "Status": "offline" } },
{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [-58.28295, 66.46454] }, "properties": { "Name": "dd", "Status": "online" } }];
var positions = { "type": "FeatureCollection", "features": cordinates };
map.setCamera({
//center map
bounds: atlas.data.BoundingBox.fromData(positions),
padding: 50
});
map.events.add('ready', function () {
//Load customized icons for use with the symbol layer.
var iconPromises = [
map.imageSprite.createFromTemplate('onlineIcon', 'marker', '#4cae4c', '#fff'),
map.imageSprite.createFromTemplate('offlineIcon', 'marker', '#808080', '#fff')
];
//Wait for icons to load into the map sprite.
Promise.all(iconPromises).then(() => {
//Create a data source to add your data to.
datasource = new atlas.source.DataSource(null, {
//Tell the data source to cluster point data.
cluster: true,
//The radius in pixels to cluster points together.
// clusterRadius: 45,
clusterProperties: { //Calculate counts for each entity type in a cluster
'online': ['+', ['case', ['==', ['get', 'Status'], 'online'], 1, 0]],
'offline': ['+', ['case', ['==', ['get', 'Status'], 'offline'], 1, 0]]
},
//The maximium zoom level in which clustering occurs.
//If you zoom in more than this, all points are rendered as symbols.
clusterMaxZoom: 24,
maxZoom: 24
});
//set data to datasource
datasource.setShapes(positions)
map.sources.add(datasource);
//Create a layer for rendering clustered data in the data source.
var clusterBubbleLayer = new atlas.layer.BubbleLayer(datasource, null, {
//Scale the size of the clustered bubble based on the number of points inthe cluster.
radius: [
'step',
['get', 'point_count'],
20, //Default of 20 pixel radius.
100, 30, //If point_count >= 100, radius is 30 pixels.
750, 40 //If point_count >= 750, radius is 40 pixels.
],
//Change the color of the cluster based on the value on the point_cluster property of the cluster.
color: [
'case', //Use a conditional case expression.
// all offline
['>', ['get', 'offline'], 0] && ['==', ['get', 'online'], 0],
'#a5a5a5',
// all online
['>', ['get', 'online'], 0] && ['==', ['get', 'offline'], 0],
'#6aa84f',
// online and offline both
'#ff9900'
],
strokeWidth: 0,
filter: ['has', 'point_count'] //Only rendered data points which have a point_count property, which clusters do.
});
//Create a layer to render the individual locations.
var shapeLayer = new atlas.layer.SymbolLayer(datasource, null, {
//Define style for individual points.
iconOptions: {
//Use a case expression to select the image icon based on the Status property of the data point.
image: [
'case',
//Check if status is online
['==', ['get', 'Status'], 'online'],
'onlineIcon',
//Offline/default icon.
'offlineIcon'
]
},
filter: ['!', ['has', 'point_count']] //Filter out clustered points from this layer.
});
//Add the clusterBubbleLayer and two additional layers to the map.
map.layers.add([
clusterBubbleLayer,
//Create a symbol layer to render the count of locations in a cluster.
new atlas.layer.SymbolLayer(datasource, null, {
iconOptions: {
image: 'none', //Hide the icon image.
},
textOptions: {
textField: '{point_count_abbreviated}',
offset: [0, 0.4]
},
filter: ['!', ['has', 'point_count']]
}),
shapeLayer
]);
markerLayer = new atlas.layer.HtmlMarkerLayer(datasource, null, {
markerCallback: function (id, position, properties) {
//Check to see if marker represents a cluster.
if (properties.cluster) {
return new atlas.PieChartMarker({
position: position,
colors: '#ffffff',
fillColor: 'white',
strokeColor: 'white',
text: properties.point_count_abbreviated
});
} else {
//for single marker
return new atlas.HtmlMarker({
visible: false
});
}
}
});
// map.events.add('click', markerLayer, markerClicked);
map.layers.add(markerLayer);
//Create an instance of the spider manager.
spiderManager = new atlas.SpiderClusterManager(map, clusterBubbleLayer, shapeLayer);
//Add event handler for when a feature is selected.
map.events.add('featureSelected', spiderManager, function (e) {
if (e.cluster) {
showPopup(e.cluster.geometry.coordinates, e.shape.getProperties(), [0, 0]);
} else {
showPopup(e.shape.getCoordinates(), e.shape.getProperties(), [0, -20]);
}
});
//Add event handler for when a feature is unselected.
map.events.add('featureUnselected', spiderManager, function () {
hidePopup();
});
});
});
}
var popupTemplate = '<div class="customInfobox"><div class="name">{name} ({status})</div></div>';
showPopup = function (position, properties, pixelOffset) {
var content = popupTemplate.replace(/{name}/g, properties.Name).replace(/{status}/g, properties.Status);
popup.setOptions({
//Update the content of the popup.
content: content,
//Update the position of the popup with the symbols coordinate.
position: position,
//Offset the popups position for better alignment with the layer.
pixelOffset: pixelOffset
});
//Open the popup.
popup.open(map);
}
hidePopup = function () {
popup.close();
}
</script>
</body>
</html>
I've also added an example to the GitHub repo for the spider cluster manager.
Upvotes: 1