I want to prevent open markers which shows after click on bubbles. Current problem is that when we click on marker then a popup opens and marker of cluster bubbles hide. And I also want to change the lines color on hover which is connecting markers after on bubble click. Below is my sample code and some screenshots:
Thank you in advance.
<!DOCTYPE html>
<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
}
.marker-container:before text {
fill: #ffffff !important;
color: #ffffff !important;
font-size: 12px !important;
}
/* .marker-container:before {
content: '2';
position: absolute;
white-space: pre;
display: inline;
top:40px;
left: 50%;
transform: translate(-50%, -25px);
} */
</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: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
}
});
var deviceList = [
{
"id": 8042,
"mac": "21june1",
"label": "21-Jun-01 - Test-1",
"dType": "mp",
"latitude": null,
"longitude": null,
"status": "offline",
"space": null
},
{
"id": 8043,
"mac": "21june2",
"label": "21june2-Test-2",
"dType": "mp",
"latitude": null,
"longitude": null,
"status": "offline",
"space": null
},
{
"id": 8044,
"mac": "21june3",
"label": "21june3-Test-3",
"dType": "mp",
"latitude": null,
"longitude": null,
"status": "offline",
"space": null
},
{
"id": 8045,
"mac": "21june4",
"label": "21june4 - Test- 4",
"dType": "mp",
"latitude": null,
"longitude": null,
"status": "offline",
"space": null
},
{
"id": 7842,
"mac": "00c3f407dc6c",
"label": "47 Billion",
"dType": "tizen",
"latitude": 22.685824,
"longitude": 75.8722663,
"status": "online",
"space": null
},
{
"id": 7934,
"mac": "b82e6e318ed3556f",
"label": "8f888a7c1385f848",
"dType": "mp",
"latitude": 22.685824,
"longitude": 75.8722663,
"status": "offline",
"space": null
},
{
"id": 7953,
"mac": "8f888a7c1385f848",
"label": "8f888a7c1385f848-kamlesh",
"dType": "mp",
"latitude": 22.1737063,
"longitude": 75.4568386,
"status": "offline",
"space": null
},
{
"id": 7949,
"mac": "a28f8e61e68b45a6",
"label": "a28f8e61e68b45a6 - MS App",
"dType": "mp",
"latitude": 22.557139462283,
"longitude": 75.810245901271,
"status": "offline",
"space": null
},
{
"id": 8048,
"mac": "45",
"label": "ak",
"dType": "mp",
"latitude": null,
"longitude": null,
"status": "offline",
"space": null
},
{
"id": 7946,
"mac": "a28f8e61e68b45a6123",
"label": "App - MS - 2",
"dType": "mp",
"latitude": 22.685824,
"longitude": 75.8722663,
"status": "offline",
"space": null
},
{
"id": 8041,
"mac": "b25a9ba7d15a",
"label": "b25a9ba7d15a-pwa",
"dType": "mp",
"latitude": null,
"longitude": null,
"status": "offline",
"space": null
},
{
"id": 8029,
"mac": "20180e107277",
"label": "COD - Eslide",
"dType": "mp",
"latitude": null,
"longitude": null,
"status": "offline",
"space": null
},
{
"id": 7844,
"mac": "d003df7e5d96-1",
"label": "d003df7e5d96 - Samsung TIzen",
"dType": "tizen",
"latitude": null,
"longitude": null,
"status": "offline",
"space": null
},
{
"id": 7969,
"mac": "d06d4e782d67ca3f",
"label": "d06d4e782d67ca3f - ankit3",
"dType": "mp",
"latitude": null,
"longitude": null,
"status": "offline",
"space": null
},
{
"id": 8039,
"mac": "53cc155a70d8",
"label": "d88d704262ca - PWA",
"dType": "mp",
"latitude": null,
"longitude": null,
"status": "offline",
"space": null
},
{
"id": 8010,
"mac": "f1sadsa",
"label": "f1f1f1msf1f1f1ms-f1f1f1ms-f1f1f1msf1f1f1ms-f1f1f1msf1f1f1msf1f1f1ms-f1f1f1msf1f1f1msf1f1f1msf1f1f1ms",
"dType": "mp",
"latitude": null,
"longitude": null,
"status": "offline",
"space": null
},
{
"id": 8046,
"mac": "f9846974-24fc-4271-b75a-84a7601c5b7b",
"label": "geo Device",
"dType": "gf",
"latitude": null,
"longitude": null,
"status": "offline",
"space": null
},
{
"id": 8040,
"mac": "d72492ca-5814-4e05-b8ae-b7f8b4cff5ce",
"label": "Geo fence Device",
"dType": "gf",
"latitude": null,
"longitude": null,
"status": "offline",
"space": null
},
{
"id": 8015,
"mac": "6905cdc3-6efb-4727-8305-018244003b18",
"label": "GF-AK",
"dType": "gf",
"latitude": 22.557139462283,
"longitude": 75.810245901271,
"status": "offline",
"space": null
},
{
"id": 7888,
"mac": "grtest1",
"label": "grtest - update",
"dType": "mp",
"latitude": null,
"longitude": null,
"status": "offline",
"space": null
},
{
"id": 7916,
"mac": "hs-test-22",
"label": "hs-test-2 edit",
"dType": "mp",
"latitude": null,
"longitude": null,
"status": "offline",
"space": null
},
{
"id": 8034,
"mac": "785dc8c72f6e",
"label": "Left Device\"",
"dType": "webos",
"latitude": 22.685824,
"longitude": 75.8722663,
"status": "online",
"space": 3897624
},
{
"id": 7945,
"mac": "c0de742442c77ccc",
"label": "MS - App\"",
"dType": "mp",
"latitude": 24.756808311193,
"longitude": 72.92724609375,
"status": "offline",
"space": null
},
{
"id": 8047,
"mac": "mc1",
"label": "MS - App\"-1",
"dType": "mc",
"latitude": null,
"longitude": null,
"status": "offline",
"space": null
},
{
"id": 8035,
"mac": "b4b291180119",
"label": "Right Device",
"dType": "webos",
"latitude": 22.1737063,
"longitude": 75.4568386,
"status": "online",
"space": 3836160
},
{
"id": 7962,
"mac": "91581699f87d1663",
"label": "Samsung Tab",
"dType": "mp",
"latitude": null,
"longitude": null,
"status": "offline",
"space": null
},
{
"id": 7965,
"mac": "e244e6cc9c428e50",
"label": "Samsung Tab - release version",
"dType": "mp",
"latitude": null,
"longitude": null,
"status": "offline",
"space": null
},
{
"id": 7960,
"mac": "ebfd9c9d0931e463",
"label": "shivam-mob",
"dType": "mp",
"latitude": null,
"longitude": null,
"status": "offline",
"space": null
},
{
"id": 8016,
"mac": "8c8d28396f25",
"label": "Vipul",
"dType": "mp",
"latitude": 23.324307764205,
"longitude": 69.406630365414,
"status": "online",
"space": null
}
];
var cordinates = [];
deviceList.forEach(function (item) {
if (item.latitude != null && item.longitude != null) {
cordinates.push({ "type": "Feature", "geometry": { "type": "Point", "coordinates": [item.longitude, item.latitude] }, "properties": { "Name": item.label, "Status": item.status } })
}
});
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);
//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,
//radius will be always 0.1
clusterRadius: 0.1,
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',
'rgba(165, 165, 165,0.6)',
// all online
['>', ['get', 'online'], 0] && ['==', ['get', 'offline'], 0],
// '#6aa84f',
'rgba(106, 168, 79,0.6)',
// online and offline both
// '#ff9900',
'rgba(255, 153, 0,0.6)',
],
strokeWidth: 0,
// textOptions:{
// textField: '{point_count}',
// },
filter: ['has', 'point_count'] //Only rendered data points which have a point_count property, which clusters do.
});
var shapeLayer = new atlas.layer.SymbolLayer(datasource, null, {
//Define style for individual points.
iconOptions: {
allowOverlap: true,
ignorePlacement: true,
opacity: 1,
//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'
]
},
textOptions: {
textField: ['get', 'point_count_abbreviated'],
offset: [0, 0.4]
},
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: ['get', 'point_count_abbreviated'],
offset: [0, 0.4],
color: 'white'
},
// filter: ['!', ['has', 'point_count']]
}),
shapeLayer
]);
//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) {
console.warn("sdfdsf");
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>
There is an option to customize the style of those lines stickLayerOptions
. The hover style is defined as part of the feature-state
so you can use a data driven style expression to customize the options. Here is how you would make that line purple when hovering.
spiderManager.setOptions({
stickLayerOptions : {
strokeColor: [
'case',
['boolean', ['feature-state', 'hover'], false],
'purple',
'black'
]
}
});
Looking through the code for the spider cluster library, it looks like when a click event occurs, the cluster closes automatically. I don't see an option to prevent that from happening. I'll take a look later today to see if there is a way to modify the library to support this scenario somehow.