Store Locator using Studio Query Data Source
This guide shows you how to build a store locator from scratch using store locations previously uploaded to the online Map Studio in GeoJSON format using queries around a searched location and a distance radius.
The finished example will look like this:
When to use
- The entire store location data set is relatively big.
- The data set is changing frequently.
What is needed
- Magic Lane API key token
- Web server (an example is provided)
- SVG file of the store logo (or use our sample SVG)
- Store locations in GeoJSON format previously uploaded to the online Map Studio and saved to datasets
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 stores data
- JavaScript
- HTML
// Start by setting your token from https://www.magiclane.com/api/projects
if (gem.core.App.token === undefined) gem.core.App.token = '';
const studioQueryControl = new gem.control.StudioQueryDataControl('1973209755' /* studio data source id */, '', {
markerBubble: {
title: ['name'],
image: ['preview']
},
markerGrouping: {
maxLevel: 14
}
});
const searchControl = new gem.control.DataQuerySearchControl({
highlightOptions: {
contourColor: { r: 0, g: 255, b: 0, a: 0 }
},
searchPreferences: {
maximumMatches: 4,
addressSearch: false,
mapPoisSearch: false,
setCursorReferencePoint: true
},
searchResults: {
initialPlaceSearch: 'Paris'
}
}, studioQueryControl);
const defaultAppScreen = gem.core.App.initAppScreen({
container: 'map-canvas',
center: [48.8562, 2.3516, 10000]
});
defaultAppScreen.addControl(studioQueryControl);
defaultAppScreen.addControl(searchControl);
gem.core.App.initAppScreen
is used to initialize the map. The map is rendered in the div
container with the id map-canvas
in the HTML page.
The map is centered on the specified position, given as latitude and longitude (in degrees) and altitude (in meters).
gem.control.StudioQueryDataControl()
is used to add GeoJSON data previously saved in the online Map Studio.
The id of the dataset from the Map Studio is provided, along with options on how to populate the marker bubble information.
The store locations are added to the map: defaultAppScreen.addControl(studioQueryControl);
gem.control.DataQuerySearchControl
is used to add search control integrated with the studio query control. The free text search result is used as a reference location for searching for stores data around the picked location using a 10 km radius (default setting).
<html lang="en-us">
<meta charset="utf-8" />
<head>
<link rel="stylesheet" type="text/css" href="https://www.magiclane.com/sdk/js/gem.css">
<title>Studio Query Controls - MagicLane Maps SDK for JavaScript</title>
</head>
<body>
<div id="storeLocator" style="width: 100%; height: 100%;">
<div id="map-canvas" style="width: 100%; height: 100%; position: absolute;"></div>
</div>
<script type="text/javascript" src="https://www.magiclane.com/sdk/js/gemapi.js"></script>
<script type="text/javascript" src="token.js"></script>
<script type="text/javascript" src="storeStudioDataQuery01.js"></script>
</body>
</html>
The map-canvas
is the drawing area where the map is rendered. The canvas is configured to fill the browser window.
At the bottom, gemapi.js, the Maps SDK for JavaScript is loaded.
Next, the JavaScript source of this example is loaded.
Adding stores list
To display a list of the store locations add a menu list container to your HTML file and the following JavaScript code:
- JavaScript
- HTML
const listUIControl = new gem.control.ListControl({
sourceControl: studioQueryControl,
flyToItemAltitude: 300,
container: 'stores-list',
menuName: 'Studio Query Data Example',
titleProperties: ['name'],
detailsProperties: ['kinds'],
imageProperty: ['preview']
});
defaultAppScreen.addControl(listUIControl);
<div id="storeLocator" style="width: 100%; height: 100%;">
<div id="stores-list" style="width: 30%; height: 100%; position: absolute;"></div>
<div id="map-canvas" style="width: 70%; height: 100%; position: absolute; left: 30%;"></div>
</div>
Adding a distance filter
To add distance filter functionality simply add the following JavaScript and HTML code:
- JavaScript
- HTML
const distanceFilterControl = new gem.control.DistanceFilterControl({
parentContainer: 'filter-distance',
name: 'byDistance',
title: 'Search radius (km)',
thresholds: [10, 25, 50, 100],
eUnit: 'km'
}, studioQueryControl);
defaultAppScreen.addControl(distanceFilterControl);
<style>
.filters-container {
position: absolute;
width: 21%;
max-width: 300px;
right: 0px;
top: 50px;
margin: 8px;
z-index: 9;
background-color: white;
box-shadow: 0 2px 4px rgb(0 0 0 / 20%), 0 -1px 0 rgb(0 0 0 / 2%);
}
</style>
</head>
<body>
<div id="storeLocator" style="width: 100%; height: 100%">
<div id="stores-list" style="width: 30%; height: 100%; position: absolute"></div>
<div id="map-canvas" style="width: 70%; height: 100%; position: absolute; left: 30%"></div>
<div id="filters-container" class="filters-container">
<div id="filter-distance" class="filter-distance"></div>
</div>
</div>
Complete example code
- JavaScript
- HTML
// Start by setting your token from https://www.magiclane.com/api/projects
if (gem.core.App.token === undefined) gem.core.App.token = '';
const studioQueryControl = new gem.control.StudioQueryDataControl('1973209755' /* studio data source id */, '', {
markerBubble: {
title: ['name'],
image: ['preview']
},
markerGrouping: {
maxLevel: 14
}
});
const listUIControl = new gem.control.ListControl({
sourceControl: studioQueryControl,
flyToItemAltitude: 300,
container: 'stores-list',
menuName: 'Studio Query Data Example',
titleProperties: ['name'],
detailsProperties: ['kinds'],
imageProperty: ['preview']
});
const searchControl = new gem.control.DataQuerySearchControl({
highlightOptions: {
contourColor: { r: 0, g: 255, b: 0, a: 0 }
},
searchPreferences: {
maximumMatches: 4,
addressSearch: false,
mapPoisSearch: false,
setCursorReferencePoint: true
},
searchResults: {
initialPlaceSearch: 'Paris'
}
}, studioQueryControl);
const distanceFilterControl = new gem.control.DistanceFilterControl({
parentContainer: 'filter-distance',
name: 'byDistance',
title: 'Search radius (km)',
thresholds: [10, 25, 50, 100],
eUnit: 'km'
}, studioQueryControl);
const defaultAppScreen = gem.core.App.initAppScreen({
container: 'map-canvas',
center: [48.8562, 2.3516, 10000]
});
defaultAppScreen.addControl(studioQueryControl);
defaultAppScreen.addControl(listUIControl);
defaultAppScreen.addControl(searchControl);
defaultAppScreen.addControl(distanceFilterControl);
<!doctype html>
<html lang="en-us">
<meta charset="utf-8" />
<head>
<link rel="stylesheet" type="text/css" href="https://www.magiclane.com/sdk/js/gem.css" />
<title>Studio Query Controls - MagicLane Maps SDK for JavaScript</title>
<style>
.filters-container {
position: absolute;
width: 21%;
max-width: 300px;
right: 0px;
top: 50px;
margin: 8px;
z-index: 9;
background-color: white;
box-shadow: 0 2px 4px rgb(0 0 0 / 20%), 0 -1px 0 rgb(0 0 0 / 2%);
}
</style>
</head>
<body>
<div id="storeLocator" style="width: 100%; height: 100%">
<div id="stores-list" style="width: 30%; height: 100%; position: absolute"></div>
<div id="map-canvas" style="width: 70%; height: 100%; position: absolute; left: 30%"></div>
<div id="filters-container" class="filters-container">
<div id="filter-distance" class="filter-distance"></div>
</div>
</div>
<script type="text/javascript" src="https://www.magiclane.com/sdk/js/gemapi.js"></script>
<script type="text/javascript" src="token.js"></script>
<script type="text/javascript" src="storeStudioDataQuery03.js"></script>
</body>
</html>
Files
The finished example consists of the project directory containing 2 files:
- JavaScript code (
.js
file extension) - HTML code (
.html
file extension)
To run the example, the HTML file is loaded in a browser.
Source code for this example:
Right-click on the links and select Save As.
Related
See Store Locator using SQL Server as Data Source for an example with GeoJSON data queried dynamically using SQL from a server, and rendered on the map.
See Store Locator using GeoJSON File as Data Source with Custom Controls for an example with GeoJSON data loaded from a file rendered on the map with custom list and search control.
See Store Locator using GeoJSON Text String as Data Source for an example with GeoJSON data defined in a variable in JavaScript, and rendered on the map.
See Store Locator using a GeoJSON File as Data Source for an example with GeoJSON data loaded from a file, and rendered on the map.
JavaScript Examples
Maps SDK for JavaScript Examples can be downloaded or cloned with Git