Skip to Content
ExamplesInteractive MapUsing app panels with interactive map

JavaScript SDK - 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.

Panels with interactive map example

<!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 AerisWeather('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>
© 2026 Xweather (opens in a new tab)Terms of Service (opens in a new tab)Privacy Policy (opens in a new tab)