Skip to content

Store Locator with Custom Markers Using Data Labels

This guide shows how the appearance of the markers style can be customized using properties available in the data source.
The finished example will look like this:

See the example fullscreen

What is needed

  • Magic Lane API key token

  • Web server

Setup

Get your Magic Lane API key token: if you do not have a token, see the Getting Started guide.

This project needs a web server. If you do not have access to a web server, you can easily install a local web server, see the Installing a Local Web Server guide. In this project we use a local web server.

Adding controls

To see how to style the marker groups check out the guide Store Locator with different Marker Groups Styles.
To learn how to customize the free text search control check out the guide Free Text Search.

Adding Custom Markers with Data Labels



How it works

 1 let geojsonDataControl = new gem.control.GeoJsonAddedDataControl("Madrid_shops.geojson", "" /*icon*/, ""/*iconFilter*/, {
 2     marker: {
 3             width: 45,
 4             height: 45,
 5             hoverWidth: 45,
 6             hoverHeight: 45,
 7             cssClass: 'store-marker',
 8             highlightClass: 'highlight-store-marker',
 9             markerFunction: function (itemInfoString) {
10                     let labelDiv = document.createElement('div');
11                     labelDiv.className = 'store-marker-text';
12                     let textlabel = labelDiv.appendChild(document.createElement('span'));
13                     let jsonInfo = JSON.parse(itemInfoString);
14                     if (jsonInfo.properties.rate)
15                             textlabel.innerHTML = 'rate ' + jsonInfo.properties.rate;
16                     else
17                             textlabel.innerHTML = 'rate n.a.';
18                     return labelDiv;
19             }
20     },
21     markerGrouping: {
22             maxLevel: 15,
23             style: gem.control.MarkersGroupStyleType.circle
24     },
25     markerBubble: {
26             title: ['name'],
27             image: ['preview']
28     }
29 });

To customize the markers with data labels you can use the data source control options:

  • marker.cssClass - specify custom style rules class for markers

  • marker.markerFunction - specify how to style the marker inner elements and optionally use the item data to add labels or filters to the marker

 1 <style>
 2   .store-marker {
 3     background-image: url(./custom.svg);
 4     background-position: center;
 5     background-repeat: no-repeat;
 6     background-size: contain;
 7     width: 45px;
 8     height: 45px;
 9     position: absolute;
10     margin: 0px auto;
11     cursor: pointer;
12     text-align: center;
13   }
14
15   .store-marker.active {
16     filter: hue-rotate(200deg) contrast(1.5);
17   }
18
19   .store-marker-text {
20     display: inline-block;
21     position: relative;
22     border-radius: 50%;
23     max-width: 30px;
24     min-width: 18px;
25     min-height: 10px;
26     text-align: center;
27     font-weight: 600;
28     top: 5px;
29     line-height: 9px;
30     -webkit-touch-callout: none;
31     -webkit-user-select: none;
32     -khtml-user-select: none;
33     -moz-user-select: none;
34     -ms-user-select: none;
35     user-select: none;
36     color: white;
37   }
38
39   .store-marker-text span {
40     font-size: 0.6rem;
41     margin: 0px;
42   }
43
44   .highlight-store-marker {
45     filter: hue-rotate(80deg) contrast(1.5);
46   }
47 </style>

Complete example code

 1 // Start by setting your token from https://developer.magiclane.com/api/projects
 2 if (gem.core.App.token === undefined)
 3     gem.core.App.token = "";
 4
 5 var defaultAppScreen = gem.core.App.initAppScreen({
 6     container: "map-canvas",
 7     zoom: 10,
 8     center: [40.431404, -3.680445], // Madrid
 9     style: "./Printemps.style"
10 });
11
12 let geojsonDataControl = new gem.control.GeoJsonAddedDataControl("Madrid_shops.geojson", "" /*icon*/, ""/*iconFilter*/, {
13     marker: {
14             width: 45,
15             height: 45,
16             hoverWidth: 45,
17             hoverHeight: 45,
18             cssClass: 'store-marker',
19             highlightClass: 'highlight-store-marker',
20             markerFunction: function (itemInfoString) {
21                     let labelDiv = document.createElement('div');
22                     labelDiv.className = 'store-marker-text';
23                     let textlabel = labelDiv.appendChild(document.createElement('span'));
24                     let jsonInfo = JSON.parse(itemInfoString);
25                     if (jsonInfo.properties.rate)
26                             textlabel.innerHTML = 'rate ' + jsonInfo.properties.rate;
27                     else
28                             textlabel.innerHTML = 'rate n.a.';
29                     return labelDiv;
30             }
31     },
32     markerGrouping: {
33             maxLevel: 15,
34             style: gem.control.MarkersGroupStyleType.circle
35     },
36     markerBubble: {
37             title: ['name'],
38             image: ['preview']
39     }
40 });
41
42 let listUIControl = new gem.control.ListControl({
43     sourceControl: geojsonDataControl,
44     container: "menu-list-container",
45     displayCount: true,
46     flyToItemAltitude: 250,
47     menuName: 'Marker Data Labels, GeoJSON data source',
48     titleProperties: ['name'],
49     detailsProperties: ['kinds'],
50         imageProperty: ['preview']
51 });
52
53 defaultAppScreen.addControl(geojsonDataControl);
54 defaultAppScreen.addControl(listUIControl);
55
56 let searchControl = new gem.control.SearchControl({
57     highlightOptions: {
58             contourColor: { r: 0, g: 255, b: 0, a: 0 }
59     },
60     searchPreferences: {
61             maximumMatches: 3,
62             addressSearch: true,
63             mapPoisSearch: true,
64             setCursorReferencePoint: true
65     }
66 });
67 defaultAppScreen.addControl(searchControl);
 1 <!DOCTYPE html>
 2 <html lang="en-us">
 3   <head>
 4     <meta charset="utf-8" />
 5     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, minimum-scale=1, user-scalable=no, shrink-to-fit=no" />
 6     <title>Markers Data Labels</title>
 7     <link rel="stylesheet" type="text/css" href="https://www.magiclane.com/sdk/js/gem.css">
 8     <link rel="stylesheet" href="/fonts/webfonts.css" type="text/css" media="all" />
 9
10     <style>
11       .store-marker {
12         background-image: url(./custom.svg);
13         background-position: center;
14         background-repeat: no-repeat;
15         background-size: contain;
16         width: 45px;
17         height: 45px;
18         position: absolute;
19         margin: 0px auto;
20         cursor: pointer;
21         text-align: center;
22       }
23
24       .store-marker.active {
25         filter: hue-rotate(200deg) contrast(1.5);
26       }
27
28       .store-marker-text {
29         display: inline-block;
30         position: relative;
31         border-radius: 50%;
32         max-width: 30px;
33         min-width: 18px;
34         min-height: 10px;
35         text-align: center;
36         font-weight: 600;
37         top: 5px;
38         line-height: 9px;
39         -webkit-touch-callout: none;
40         -webkit-user-select: none;
41         -khtml-user-select: none;
42         -moz-user-select: none;
43         -ms-user-select: none;
44         user-select: none;
45         color: white;
46       }
47
48       .store-marker-text span {
49         font-size: 0.6rem;
50         margin: 0px;
51       }
52
53       .highlight-store-marker {
54         filter: hue-rotate(80deg) contrast(1.5);
55       }
56     </style>
57   </head>
58
59   <body>
60     <div id="store-locator" style="width: 100%; height: 100%">
61       <div id="menu-list-container" class="menu-list-container" style="width: 30%; height: 100%; position: absolute"></div>
62       <div id="map-canvas" style="width: 70%; left: 30%; height: 100%; position: absolute; overflow: hidden"></div>
63     </div>
64
65     <script src="https://www.magiclane.com/sdk/js/gemapi.js"></script>
66     <script type="text/javascript" src="token.js"></script>
67     <script type="text/javascript" src="storeGeoJSONDataMarkers.js"></script>
68   </body>
69 </html>

Files


JavaScript
HTML
Printemps Map Style
GeoJSON data downloaded from OpenTripMap:
Madrid Shops Example GeoJSON
Icon customized from Iconpacks:
Custom Marker Image