---
title: "Weather Cloud coverage displayed from radar data | Weather SDK | JavaScript maps SDK"
description: "Visualize cloud coverage using weather radar data and tooltips."
---

> For AI agents: a documentation index is available at [/llms.txt](https://docs.maptiler.com/llms.txt). Markdown versions of all pages are available by appending .md to any URL.

# 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

```bash
npm install --save @maptiler/sdk @maptiler/weather
```

#### main.js

```js
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);
});
```

#### index.html

```html
<!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>
```

#### style.css

```css
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;
}
```

### Basic JavaScript setup

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Cloud coverage displayed from radar data</title>
  <script src="https://cdn.maptiler.com/maptiler-sdk-js/v4.2.0/maptiler-sdk.umd.min.js"></script>
  <link href="https://cdn.maptiler.com/maptiler-sdk-js/v4.2.0/maptiler-sdk.css" rel="stylesheet" />
  <script src="https://cdn.maptiler.com/maptiler-weather/v4.0.1/maptiler-weather.umd.min.js"></script>
  <style>
    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;
    }
  </style>
</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>
      maptilersdk.config.apiKey = 'YOUR_MAPTILER_API_KEY_HERE';
      const map = (window.map = new maptilersdk.Map({
        container: 'map', // container's id or the HTML element to render the map
        style: maptilersdk.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 maptilerweather.RadarLayer({
        opacity: 0.8,
        colorramp: maptilerweather.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);
      });

  </script>
</body>
</html>
```

## Learn more

Check out the [Weather JS module reference](https://docs.maptiler.com/sdk-js/modules/weather/)

Check out the [Radar layer reference](https://docs.maptiler.com/sdk-js/modules/weather/api/radar/)

Check out the [Color ramp reference](https://docs.maptiler.com/sdk-js/modules/weather/api/color-ramp/)

## Related examples

### [Weather custom popup](https://docs.maptiler.com/sdk-js/examples/weather-custom-popup/)

Examples

Create highly customizable popups for weather maps using MarkerLayout.

### [Weather layer switcher](https://docs.maptiler.com/sdk-js/examples/weather-layer-switcher/)

Examples

Switch weather layers and view detailed data under cursors.

### [Weather precipitation layer](https://docs.maptiler.com/sdk-js/examples/weather-precipitation/)

Examples

Visualize precipitation layers and view localized data under cursors.

### [Weather+ pressure isolines layer](https://docs.maptiler.com/sdk-js/examples/weather-plus-pressure-isolines/)

Examples

Visualize atmospheric pressure isolines using Weather Plus datasets.
