Weather Cloud coverage displayed from radar data
Explore the weather cloud coverage on a weather radar map using the MapTiler Weather Radar dataset and get the radar reflectivity in dBZ at the point under the cursor.
This example, illustrates the process of visualizing cloud cover, using the built-in RADAR_CLOUD color ramp.
NPM module setup
npm install --save @maptiler/sdk @maptiler/weather
import { Map, MapStyle, config } from '@maptiler/sdk';
import '@maptiler/sdk/dist/maptiler-sdk.css';
import { RadarLayer, ColorRamp } from '@maptiler/weather';
config.apiKey = 'YOUR_MAPTILER_API_KEY_HERE';
const map = (window.map = new Map({
container: 'map', // container's id or the HTML element to render the map
style: MapStyle.BACKDROP.LIGHT,
zoom: 1,
center: [-15.5, 15.2],
hash: true,
projectionControl: true,
}));
const timeInfoContainer = document.getElementById("time-info");
const timeTextDiv = document.getElementById("time-text");
const timeSlider = document.getElementById("time-slider");
const playPauseButton = document.getElementById("play-pause-bt");
const pointerDataDiv = document.getElementById("pointer-data");
let pointerLngLat = null;
const weatherLayer = new RadarLayer({
opacity: 0.8,
colorramp: ColorRamp.builtin.RADAR_CLOUD,
});
// Event called when all the datasource for the next days are added and ready.
// From now on, the layer nows the start and end dates.
weatherLayer.on("sourceReady", event => {
const startDate = weatherLayer.getAnimationStartDate();
const endDate = weatherLayer.getAnimationEndDate();
const currentDate = weatherLayer.getAnimationTimeDate();
refreshTime()
timeSlider.min = +startDate;
timeSlider.max = +endDate;
timeSlider.value = +currentDate;
})
timeSlider.addEventListener("input", (evt) => {
weatherLayer.setAnimationTime(parseInt(timeSlider.value / 1000))
});
// Called when the animation is progressing
weatherLayer.on("tick", event => {
refreshTime();
updatePointerValue(pointerLngLat);
});
map.on('load', function () {
map.setPaintProperty("Water", 'fill-color', "rgba(0, 0, 0, 0.4)");
map.addLayer(weatherLayer, 'Water');
});
map.on('mouseout', function(evt) {
if (!evt.originalEvent.relatedTarget) {
pointerDataDiv.innerText = "";
pointerLngLat = null;
}
});
// Called when the time is manually set
weatherLayer.on("animationTimeSet", event => {
refreshTime()
})
// When clicking on the play/pause
let isPlaying = false;
playPauseButton.addEventListener("click", () => {
if (isPlaying) {
weatherLayer.animateByFactor(0);
playPauseButton.innerText = "Play 3600x";
} else {
weatherLayer.animateByFactor(3600);
playPauseButton.innerText = "Pause";
}
isPlaying = !isPlaying;
})
// Update the date time display
function refreshTime() {
const d = weatherLayer.getAnimationTimeDate();
timeTextDiv.innerText = d.toString();
timeSlider.value = +d;
}
function updatePointerValue(lngLat) {
if (!lngLat) return;
pointerLngLat = lngLat;
const value = weatherLayer.pickAt(lngLat.lng, lngLat.lat);
if (!value) {
pointerDataDiv.innerText = "";
return;
}
pointerDataDiv.innerText = `${value.value.toFixed(1)} dBZ`
}
timeInfoContainer.addEventListener("mouseenter", () => {
pointerDataDiv.innerText = "";
});
map.on('mousemove', (e) => {
updatePointerValue(e.lngLat);
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="robots" content="noindex">
<title>Cloud coverage displayed from radar data</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="time-info">
<span id="time-text"></span>
<button id="play-pause-bt" class="button">Play 3600x</button>
<input type="range" id="time-slider" min="0" max="11" step="1">
</div>
<div id="variable-name">Radar</div>
<div id="pointer-data"></div>
<div id="map"></div>
<script type="module" src="./main.js"></script>
</body>
</html>
body { margin: 0; padding: 0; font-family: sans-serif; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; background-color: #444952;}
#pointer-data {
z-index: 1;
position: fixed;
font-size: 20px;
font-weight: 900;
margin: 27px 0px 0px 10px;
color: #fff;
text-shadow: 0px 0px 10px #0007;
}
#variable-name {
z-index: 1;
position: fixed;
font-size: 20px;
font-weight: 500;
margin: 5px 0px 0px 10px;
color: #fff;
text-shadow: 0px 0px 10px #0007;
}
#time-info {
position: fixed;
width: 60vw;
bottom: 0;
z-index: 1;
margin: 10px;
text-shadow: 0px 0px 5px black;
color: white;
font-size: 18px;
font-weight: 500;
text-align: center;
left: 0;
right: 0;
margin: auto;
padding: 20px;
}
#time-text {
font-size: 12px;
font-weight: 600;
}
#time-slider {
width: 100%;
height: fit-content;
left: 0;
right: 0;
z-index: 1;
filter: drop-shadow(0 0 7px #000a);
margin-top: 10px;
}
.button {
cursor: pointer;
width: auto;
padding: 8px;
border-radius: 3px;
font-size: 10px;
text-align: center;
color: #fff;
background: #3174ff;
font-family: sans-serif;
font-weight: bold;
}
Learn more
Check out the Weather JS module reference
Check out the Radar layer reference
Check out the Color ramp reference
Related examples
Weather custom popup
ExamplesCreate highly customizable popups for weather maps using MarkerLayout.
Weather precipitation layer
ExamplesVisualize precipitation layers and view localized data under cursors.
Weather+ pressure isolines layer
ExamplesVisualize atmospheric pressure isolines using Weather Plus datasets.