Skip to content
Switch branches/tags
Go to file
Cannot retrieve contributors at this time
<!DOCTYPE html>
<html lang="en">
<title>Drag and drop spatial files onto map - Azure Maps Web SDK Samples</title>
<meta charset="utf-8" />
<link rel="shortcut icon" href="/favicon.ico"/>
<meta http-equiv="x-ua-compatible" content="IE=Edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="Drag and drop one or more KML, KMZ, GeoRSS, GPX, GML, GeoJSON or CSV files onto the map." />
<meta name="keywords" content="Microsoft maps, map, gis, API, SDK, KML, KMZ, GeoRSS, GPX, GML, GeoJSON, CSV, ogc, spatial data, spatial io module, geoxml" />
<meta name="author" content="Microsoft Azure Maps" />
<!-- Add references to the Azure Maps Map control JavaScript and CSS files. -->
<link rel="stylesheet" href="" type="text/css" />
<script src=""></script>
<!-- Add reference to the Azure Maps Spatial IO module. -->
<script src=""></script>
<script type='text/javascript'>
var map, datasource, imageLayers = [], layer, dataBounds, statusPanel, dataPanel, imageIcons = [], loadingIcon, fileCount = 0;
var proxyServiceUrl = window.location.origin + '/Common/CorsEnabledProxyService.ashx?url=';
function GetMap() {
statusPanel = document.getElementById('statusPanel');
dataPanel = document.getElementById('dataPanel');
loadingIcon = document.getElementById('loadingIcon');
//Point the Azure Maps domain to the US Azure Gov Cloud domain.
//Initialize a map instance.
map = new atlas.Map('myMap', {
view: 'Auto',
//Add authentication details for connecting to Azure Maps.
authOptions: {
//Use Azure Active Directory authentication.
authType: 'anonymous',
clientId: 'c9f2f391-13f1-407b-a4a5-f0a241bacfbf', //Your Azure Active Directory client id for accessing your Azure Maps account.
getToken: function (resolve, reject, map) {
//URL to your authentication service that retrieves an Azure Active Directory Token.
var tokenServiceUrl = '';
fetch(tokenServiceUrl).then(r => r.text()).then(token => resolve(token));
//Alternatively, use an Azure Maps key. Get an Azure Maps key at NOTE: The primary key should be used as the key.
//authType: 'subscriptionKey',
//subscriptionKey: '<Your Azure Maps Key>'
//Wait until the map resources are ready.'ready', function () {
//Create a style control and add it to the map.
map.controls.add(new atlas.control.StyleControl({
style: 'dark',
mapStyles: 'all'
}), {
position: 'top-right'
//Create a data source to store the data in.
datasource = new atlas.source.DataSource();
//Add a simple data layer for rendering the data.
layer = new atlas.layer.SimpleDataLayer(datasource);
//Setup the drag & drop listeners on the map.
var dropZone = document.getElementById('myMap');
dropZone.addEventListener('dragover', handleDragOver, false);
dropZone.addEventListener('drop', handleFileSelect, false);
function handleDragOver(evt) {
//Stop the browser from performing its default behavior when a file is dragged and dropped.
evt.dataTransfer.dropEffect = 'copy';
function handleFileSelect(evt) {
statusPanel.value = 'Reading from Files\r\n\r\n';
//Stop the browser from performing its default behavior when a file is dragged and dropped.
//The list of files that have been dragged and dropped onto the map.
var files = evt.dataTransfer.files;
//Loop through and attempt to read each file.
for (var i = 0; i < files.length; i++) {
//Read the data blob.
readData(files[i], files[i].name);
function readData(data, fileName) { = '';
//Attempt to parse the file and add the shapes to the map., {
proxyService: proxyServiceUrl
function (r) {
//Check to see if there is any icon data. If there is, load them into the map before loading the data.
if (r.icons) {
loadIcons(r.icons).then(function () {
loadData(r, fileName);
} else {
loadData(r, fileName);
function (msg) {
writeStats(fileName, null, msg);
function readDataPanel() {
statusPanel.value = 'Reading from Data panel\r\n\r\n';
function loadData(r, fileName) {
//Load all features.
if (r.features && r.features.length > 0) {
//Load ground overlays.
if (r.groundOverlays && r.groundOverlays.length > 0) {
imageLayers = imageLayers.concat(r.groundOverlays);
//If there is a bounding box for the data, set the map to it.
if (r.bbox) {
if (dataBounds) {
//If there are multiple files being loaded, there merge their bounding boxes together.
dataBounds =, r.bbox);
} else {
dataBounds = r.bbox;
//Update the map view.
map.setCamera({ bounds: dataBounds, padding: 50 });
//Write stats.
writeStats(fileName, r.stats);
//Load icons into the map image sprite.
function loadIcons(icons) {
return new Promise(function (resolve, reject) {
if (!icons) {
//The keys are the names of each icon image.
var keys = Object.keys(icons);
if (keys.length === 0) {
//For each icon image, create a promise to add it to the map, then run the promises in parrallel.
var imagePromises = [];
keys.forEach(function (key) {
imagePromises.push(map.imageSprite.add(key, icons[key]));
Promise.all(imagePromises).then(function () {
//Remember all the added icon names so we can remove them later when the map is cleared.
imageIcons = imageIcons.concat(keys);
//Remove any custom loaded icons from the map.
function removeIcons() {
for (var i = 0; i < imageIcons.length; i++) {
imageIcons = [];
function clearMap() {
//Remove any existing data from the map.
dataBounds = null;
imageLayers = [];
//Writes data as a string an adds to data panel.
function writeData() {
dataPanel.value = '';
var fileTypeDD = document.getElementById('fileType');
var fileType = fileTypeDD.options[fileTypeDD.selectedIndex].innerText;
var s =;, {
format: fileType,
indentChars: ' ' //Use 4 spaces instead of \t for indenting as it looks better in the textarea.
}).then(function (dataString) {
var e =;
statusPanel.value = 'Data written in: ' + (e - s) + 'ms';
dataPanel.value = dataString;
openTab(null, 'Data');
//Downloads the data as a compressed file (KMZ or ZIP).
function downloadZip() {
dataPanel.value = '';
var fileTypeDD = document.getElementById('fileType');
var fileType = fileTypeDD.options[fileTypeDD.selectedIndex].innerText;, 'Blob', {
format: fileType,
indentChars: ' ' //Use 4 spaces instead of \t for indenting as it looks better in the textarea.
}).then(function (compressedData) {
if (fileType === 'KML') {
saveAs(compressedData, 'MapData.kmz');
} else {
saveAs(compressedData, '');
//Write reading stats and errors for each file read.
function writeStats(fileName, stats, error) {
var result = [];
if (fileName) {
result.push('File name: ', fileName);
if (error) {
result.push('\r\nError: ', error);
if (stats) {
if (stats.numCharecters) {
result.push('\r\nFile size: ', Math.ceil(stats.numCharecters / 1024), ' KB');
if (stats.numPoints) {
result.push('\r\n# of Points: ', stats.numPoints);
if (stats.numLineStrings) {
result.push('\r\n# of LineStrings: ', stats.numLineStrings);
if (stats.numPolygons) {
result.push('\r\n# of Polygons: ', stats.numPolygons);
if (stats.numPositions) {
result.push('\r\n# of Positions: ', stats.numPositions);
if (stats.numNetworkLinks) {
result.push('\r\n# of Network Links: ', stats.numNetworkLinks);
if (stats.numGroundOverlays) {
result.push('\r\n# of Ground Overlays ', stats.numGroundOverlays);
result.push('\r\nProcessing time (ms): ', stats.processingTime, '\r\n\r\n');
statusPanel.value += result.join('');
if (fileCount === 0) { = 'none';
openTab(null, 'Status');
function openTab(elm, tabName) {
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
document.getElementById(tabName).style.display = "block";
if (!elm) {
if (tabName === 'Status') {
elm = document.getElementById('StatusBtn');
} else if (tabName === 'Data') {
elm = document.getElementById('DataBtn');
elm.className += " active";
#myMap {
position: relative;
width: calc(100% - 375px);
min-width: 290px;
height: 600px;
float: left;
.sidePanel {
width: 325px;
height: 580px;
float: left;
margin-right: 10px;
#Instructions {
display: block;
height: 490px;
width: 306px;
#statusPanel {
width: 300px;
height: 490px;
overflow-y: auto;
#dataPanel {
width: 300px;
height: 360px;
overflow-y: auto;
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 6px 8px;
transition: 0.3s;
font-size: 14px;
.tab button:hover {
background-color: #ddd;
.tab {
background-color: #ccc;
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
<body onload="GetMap()">
<fieldset class="sidePanel">
<legend><h1 style="font-size:16px">Drag and drop spatial files onto map</h1></legend>
<div class="tab">
<button class="tablinks active" onclick="openTab(this, 'Instructions')">Instructions</button>
<button id="StatusBtn" class="tablinks" onclick="openTab(this, 'Status')">Status</button>
<button id="DataBtn" class="tablinks" onclick="openTab(this, 'Data')">Data</button>
<div id="Instructions" class="tabcontent">
Drag and drop one or more KML, KMZ, GeoRSS, GPX, GML, GeoJSON or CSV files onto the map.<br /><br />
<select id="fileType">
<option selected="selected">KML</option>
<input type="button" value="Write data" onclick="writeData()" />
<input type="button" value="Download Zip" onclick="downloadZip()" /><br /><br />
<input type="button" value="Clear Map" onclick="clearMap();" />
<div id="Status" class="tabcontent">
<textarea id="statusPanel"></textarea>
<div id="Data" class="tabcontent">
<textarea id="dataPanel"></textarea>
<br /><br />
Add XML, GeoJSON, CSV or an URL that points to a file of these types into the data panel and press the "Read data" button to render the data on the map.
<br /><br />
<input type="button" value="Read data" onclick="readDataPanel()" />
<div id="myMap"></div>
<img id="loadingIcon" src="../Common/images/loadingIcon.gif" style="position:absolute;top:270px;left:calc(50% - 30px);display:none;" />