Skip to content
Permalink
master
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
<!DOCTYPE html>
<html lang="en">
<head>
<title>Animated tile layer - Azure Maps Web SDK Samples</title>
<meta charset="utf-8" />
<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="This sample shows how to animate an sequence of tile layers smoothly." />
<meta name="keywords" content="Microsoft maps, map, gis, API, SDK, animate, animation, tiles" />
<meta name="author" content="Microsoft Azure Maps" />
<!-- Add references to the Azure Maps Map control JavaScript and CSS files. -->
<link rel="stylesheet" href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.css" type="text/css" />
<script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.js"></script>
<!-- Add reference to the animation module. -->
<script src="../Common/scripts/azure-maps-animations.min.js"></script>
<script type='text/javascript'>
var map, layer, timer;
//Base weather tile layer URL for radar data. {azMapsDomain} is a placeholder that is set automatically by the map, and will also automatically append the map credentials to the request.
var urlTemplate = 'https://{azMapsDomain}/map/tile?api-version=2.0&tilesetId={tilesetId}&zoom={z}&x={x}&y={y}&timeStamp={timestamp}&tileSize=256&view=Auto';
//Details on the availability of the different weather layers.
var weatherLayers = {
'microsoft.weather.infrared.main': {
interval: 10 * 60 * 1000, //10 minute interval
past: 3 * 60 * 60 * 1000, //Data available up to 3 hours in the past.
future: 0 //Forecast data not avaiable.
},
'microsoft.weather.radar.main': {
interval: 5 * 60 * 1000, //5 minute interval
past: 1.5 * 60 * 60 * 1000, //Data available up to 1.5 hours in the past.
future: 1.5 * 60 * 60 * 1000 //Data available up to 1.5 hours in the future.
}
};
var displayMessages = [];
function GetMap() {
//Point the Azure Maps domain to the US Azure Gov Cloud domain.
atlas.setDomain('atlas.azure.us');
//Initialize a map instance.
map = new atlas.Map('myMap', {
center: [-95, 40],
zoom: 3,
style: 'grayscale_dark',
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 = 'https://azuremapscodesamples.azurewebsites.us/Common/TokenService.ashx';
fetch(tokenServiceUrl).then(r => r.text()).then(token => resolve(token));
}
//Alternatively, use an Azure Maps key. Get an Azure Maps key at https://azure.com/maps. NOTE: The primary key should be used as the key.
//authType: 'subscriptionKey',
//subscriptionKey: '<Your Azure Maps Key>'
}
});
//Wait until the map resources are ready.
map.events.add('ready', function () {
//Load the radar layer by default.
loadWeatherLayer('microsoft.weather.radar.main');
});
}
function loadWeatherLayer(tilesetId) {
//If there is already a layer, stop it animating.
if (layer) {
layer.stop();
clearInterval(timer);
}
//Get the current time.
var now = new Date().getTime();
//Get the details for the requested weather layer.
var layerInfo = weatherLayers[tilesetId];
//Calculate the number of timestamps.
var numTimestamps = (layerInfo.past + layerInfo.future) / layerInfo.interval;
var tlOptions = [];
for (var i = 0; i < numTimestamps; i++) {
//Calculate time period for an animation frame. Shift the interval by one as the olds tile will expire almost immediately.
var time = (now - layerInfo.past) + (i + 1) * layerInfo.interval;
//Create a tile layer option for each timestamp.
tlOptions.push(createTileLayer(tilesetId, time));
//Optionally, create a message to display for each frame of the animation based on the time stamp.
if (time === now) {
displayMessages.push('Current');
} else {
var dt = (time - now) / 1000 / 60;
displayMessages.push(`${dt} minutes`);
}
}
if (layer) {
layer.setOptions({
tileLayerOptions: tlOptions
});
layer.play();
} else {
//Create the animation manager.
layer = new atlas.layer.AnimatedTileLayer({
tileLayerOptions: tlOptions,
duration: numTimestamps * 800, //Allow one second for each frame (tile layer) in the animation.
autoPlay: true,
loop: true
});
//Add an event to the underlying frame animation to update the message panel when the frame changes.
map.events.add('onframe', layer.getPlayableAnimation(), function (e) {
if (e.frameIdx >= 0) {
var msg = displayMessages[e.frameIdx];
document.getElementById('messagePanel').innerText = msg;
}
});
//Add the layer to the map.
map.layers.add(layer, 'labels');
//Setup an interval timer to shift the layers (remove oldest, add newest) based on the update interval of the tile layer.
timer = setInterval(intervalHandler(tilesetId), layerInfo.interval);
}
}
function createTileLayer(tilesetId, time) {
//Create an ISO 8601 timestamp string.
//JavaScripts format for ISO string includes decimal seconds and the letter "Z" at the end that is not supported. Use slice to remove this.
var timestamp = new Date(time).toISOString().slice(0, 19);
//Create a tile layer option for each timestamp.
return {
tileUrl: urlTemplate.replace('{tilesetId}', tilesetId).replace('{timestamp}', timestamp),
tileSize: 256, //Weather tiles only available in 256 pixel size.
opacity: 0.9,
maxSourceZoom: 15 //Weather tiles only available to zoom level 15. If you zoom in closer, the map may pull tiles from level 15 to fill the map.
};
}
function intervalHandler(tilesetId) {
return function () {
//Get the details for the requested weather layer.
var layerInfo = weatherLayers[tilesetId];
//Calculate time period for an animation frame. Shift the interval by one as the olds tile will expire almost immediately.
var time = (now - layerInfo.past) + (i + 1) * layerInfo.interval;
//Create an ISO 8601 timestamp string.
//JavaScripts format for ISO string includes decimal seconds and the letter "Z" at the end that is not supported. Use slice to remove this.
var timestamp = new Date(time).toISOString().slice(0, 19);
//Get the current tile layer options from the animation layer.
var layers = layer.getOptions().tileLayerOptions;
//Remove the oldest tile layer options.
tlOptions.shift();
//Add the newest tile layer options.
tlOptions.push(createTileLayer(tilesetId, time));
//Update the animation layer.
layer.setOptions({ tileLayerOptions: tlOptions });
}
}
function updateTileLayer(elm) {
var tilesetId = elm.options[elm.selectedIndex].value;
loadWeatherLayer(tilesetId);
}
function setSpeed(elm) {
var speed = parseFloat(elm.options[elm.selectedIndex].value);
layer.setOptions({ speedMultiplier: speed });
}
</script>
</head>
<body onload="GetMap()">
<div id="myMap" style="position:relative;width:100%;min-width:290px;height:600px;"></div>
<div style="position:absolute;top:15px;left:15px;border-radius:5px;padding:5px;background-color:white;">
Select weather overlay:
<select onchange="updateTileLayer(this)">
<option value="microsoft.weather.radar.main" selected="selected">Radar</option>
<option value="microsoft.weather.infrared.main">Infrared</option>
</select>
<br /><br />
<input type="button" value="Play" onclick="layer.play();" />
<input type="button" value="Pause" onclick="layer.pause();" />
<input type="button" value="Stop" onclick="layer.stop();" />
<input type="button" value="Reset" onclick="layer.reset();" />
<br /><br />
Speed:
<select onchange="setSpeed(this)">
<option value="0.5">0.5x</option>
<option value="1" selected="selected">1x</option>
<option value="2">2x</option>
<option value="5">5x</option>
</select>
</div>
<div id="messagePanel" style="position: absolute;top: 20px;right: 20px;background-color: white;padding: 2px;border-radius: 15px;width: 110px;text-align: center;"></div>
<fieldset style="width:calc(100% - 30px);min-width:290px;margin-top:10px;">
<legend><h1 style="font-size:16px">Animated tile layer</h1></legend>
This sample shows how to animate an sequence of tile layers smoothly.
This example uses the AnimatedTileLayer to animate through an array of tile layers.
For this sample weather data from Azure Maps through the <a href="https://docs.microsoft.com/en-us/rest/api/maps/renderv2/getmaptilepreview">Reader services</a> are used.
Infrared data is updated every 10 minutes and available for 3 hours in the past. Radar data updated every 5 minutes and available 1.5 hours past and future forecast.
This sample uses the open source <a href="https://github.com/Azure-Samples/azure-maps-animations" target="_blank">Azure Maps Animation module</a>
</fieldset>
</body>
</html>