Using App Panels with InteractiveMap
Render a basic interactive map with various panels and controls used by InteractiveMapApp
and provided by the Apps module. The following example will display an interactive map with the timeline, legend, place search and local weather info panels similar to InteractiveMapApp
but without the auto-managed map app container.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Aeris JavaScript SDK - Using App Panels with Interactive Map</title>
<script defer src="https://cdn.aerisapi.com/sdk/js/latest/aerisweather.min.js"></script>
<link rel="stylesheet" href="https://cdn.aerisapi.com/sdk/js/latest/aerisweather.css">
<style>
#map-container {
font-family: 'Helvetica','Aerial',sans-serif;
height: 800px;
margin: 30px auto;
position: relative;
width: 1200px;
}
#map {
height: inherit;
width: 100%;
}
</style>
</head>
<body>
<div id="map-container">
<div id="map"></div>
</div>
<script>
window.onload = () => {
const aeris = new Xweather('CLIENT_ID', 'CLIENT_SECRET');
aeris.views().then(views => {
const map = new views.InteractiveMap(document.getElementById('map'), {
center: {
lat: 39.0,
lon: -95.5
},
zoom: 4,
layers: 'alerts,radar',
timeline: {
from: -6 * 3600,
to: 0
}
});
aeris.apps().then((apps) => {
const container = document.getElementById('map-container');
const account = aeris.account();
// map timeline
const timeline = new apps.panels.TimelinePanel(map.timeline);
timeline.addTo(container);
timeline.pinTo('bottom', { y: -10 });
// place search
const search = new apps.panels.PlaceSearchPanel({
account
});
search.on('select', (e) => {
const { result: { loc }} = e.data || {};
if (loc) {
const { lat, long: lon } = loc;
const coord = { lat, lon };
map.setView(coord, 8);
}
});
search.addTo(container);
search.pinTo('top', { y: 10 });
// legends
const legends = new apps.panels.LegendPanel({
toggleable: true
});
legends.addTo(container);
legends.pinTo('bottomright', { x: -10, y: -10 });
// set up events on map layer add/remove to update legends
map.on('layer:add', (e) => {
const { layer, id } = e.data || {};
const keys = layer || id;
if (keys) {
const layers = keys.replace(/\:[^,]+/g, '').split(',');
layers.forEach((code) => {
legends.legend.add(code, {
account: account
});
if (code === 'alerts' || /^alerts-/.test(code)) {
setTimeout(() => {
legends.legend.update({
account: account,
within: {
bounds: map.getBounds()
}
});
}, 500);
}
});
}
}).on('layer:remove source:remove', (e) => {
const { layer, id } = e.data || {};
const keys = layer || id;
if (keys) {
const layers = keys.replace(/\:[^,]+/g, '').split(',');
layers.forEach((code) => {
legends.legend.remove(code);
});
}
}).on('change:bounds', (e) => {
const opts = { account: account };
opts.within = {
bounds: map.getBounds()
};
legends.legend.update(opts);
});
// info panel
const infoPanel = new apps.panels.InfoPanel();
// set up the localweather view configuration and requests that will be used in the InfoPanel
infoPanel.setContentView('localweather', {
request: () => {
const request = account.api();
const forecastFields = (`
timestamp,dateTimeISO,tempF,tempC,icon,weatherPrimary,windSpeedMPH,windSpeedKPH,windSpeedMinMPH,windSpeedMinKPH,
windSpeedMaxMPH,windSpeedMaxKPH,windGustMPH,windGustKPH,snowIN,snowCM,precipIN,precipMM
`).split(',').map((key) => `periods.${key}`);
request.addRequest(account.api().endpoint('forecasts').fields(forecastFields.join(',')).filter('3hr').limit(7));
request.addRequest(account.api().endpoint('places'));
request.addRequest(account.api().endpoint('observations'));;
return request;
},
views: [{
renderer: 'place'
},{
title: 'Observations',
renderer: 'obs'
},{
title: 'Short-Term Forecast',
renderer: 'forecast'
}]
});
infoPanel.addTo(container);
infoPanel.pinTo('topleft', { x: 10, y: 10 });
// show InfoPanel for location when map is clicked
map.on('click', (e) => {
const { coord: { lat, lon }} = e.data || {};
infoPanel.showContent('localweather', 'Local Weather').load({
p: `${lat},${lon}`
});
});
})
});
};
</script>
</body>
</html>