---
title: "Weather Plus pressure isolines layer animated | Weather SDK | Weather plus | JavaScript maps SDK"
description: "Animate atmospheric pressure isolines and view precise cursor data."
---

> 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 Plus pressure isolines layer animated

Explore the weather [pressure isolines layer](https://docs.maptiler.com/sdk-js/modules/weather/api/pressure-isolines/) from [MapTiler Weather Plus](https://www.maptiler.com/weather/) Pressure dataset. By accessing the Pressure dataset, you can visualize the distribution of pressure across different locations. With just a simple cursor movement, you can retrieve the precise pressure value at any given point.

The [`showPressureLabels` function](https://docs.maptiler.com/sdk-js/modules/weather/api/isolines/#methods#showPressureLabels), allows you to view the highest and lowest pressure extremes on the map. This provides valuable insights into the atmospheric conditions and helps you understand the dynamics of weather patterns.

To enhance your experience, we have incorporated an animation bar that illustrates the movement of isobars over a four-day time period. This dynamic representation allows you to track changes in pressure over time and gain a deeper understanding of weather trends. Additionally, we have included a button that enables the display of Hi/Lo pressure extreme values labels, ensuring that you have all the necessary information at your fingertips.

### NPM module setup

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

#### main.js

```js
import { Map, MapStyle, config } from '@maptiler/sdk';
import '@maptiler/sdk/dist/maptiler-sdk.css';
import { PressureIsolineLayer } from '@maptiler/weather-plus';

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,  // stylesheet location
  projectionControl: true,
  zoom: 1,
  center: [-15.5, 15.2],
  hash: 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 labelsButton = document.getElementById("show-labels");
const pointerDataDiv = document.getElementById("pointer-data");
let pointerLngLat = null;
let hasLabels = false;

const weatherLayer = new PressureIsolineLayer({
  opacity: 0.8,
});

map.on('load', function () {
  map.setPaintProperty("Water", 'fill-color', "rgba(0, 0, 0, 0.4)");
  map.addLayer(weatherLayer, 'Water');  
});

timeSlider.addEventListener("input", (evt) => {
  weatherLayer.setAnimationTime(parseInt(timeSlider.value / 1000));
  hideLabels();
});

// 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;
});

// Called when the animation is progressing
weatherLayer.on("tick", event => {
  refreshTime();
  updatePointerValue(pointerLngLat);
});

// 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";
    labelsButton.disabled = false;
  } else {
    weatherLayer.animateByFactor(3600);
    playPauseButton.innerText = "Pause";
    hideLabels();
    labelsButton.disabled = true;
  }
  isPlaying = !isPlaying;
});

labelsButton.addEventListener("click", () => {
  if (!isPlaying && !hasLabels) {
    weatherLayer.showPressureLabels();
    hasLabels = true;
    labelsButton.innerText = "Hide labels";
  } else {
    hideLabels();
  }
});

function hideLabels() {
  weatherLayer.hidePressureLabels();
  hasLabels = false;
  labelsButton.innerText = "Show labels";
}

// Update the date time display
function refreshTime() {
  const d = weatherLayer.getAnimationTimeDate();
  timeTextDiv.innerText = d.toString();
  timeSlider.value = +d;
}

map.on('mouseout', function(evt) {
  if (!evt.originalEvent.relatedTarget) {
    pointerDataDiv.innerText = "";
    pointerLngLat = null;
  }
});

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)} hPa`
}

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>Display a pressure isolines layer</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>
    <div><button id="show-labels" class="button">Show labels</button></div>
    <input type="range" id="time-slider" min="0" max="11" step="1">
  </div>
  <div id="variable-name">Pressure</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;}
#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-slider{ width: 100%; height: fit-content; left: 0; right: 0; z-index: 1; filter: drop-shadow(0 0 7px #000a); margin-top: 10px;}
#time-text{ font-size: 12px; font-weight: 600;}
#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;}
.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>Display a pressure isolines layer</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="./maptiler-weather-plus.umd.js"></script>
  <style>
    body { margin: 0; padding: 0; font-family: sans-serif; }
    #map { position: absolute; top: 0; bottom: 0; width: 100%; background-color: #444952;}
    #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-slider{ width: 100%; height: fit-content; left: 0; right: 0; z-index: 1; filter: drop-shadow(0 0 7px #000a); margin-top: 10px;}
    #time-text{ font-size: 12px; font-weight: 600;}
    #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;}
    .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>
    <div><button id="show-labels" class="button">Show labels</button></div>
    <input type="range" id="time-slider" min="0" max="11" step="1">
  </div>
  <div id="variable-name">Pressure</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,  // stylesheet location
        projectionControl: true,
        zoom: 1,
        center: [-15.5, 15.2],
        hash: 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 labelsButton = document.getElementById("show-labels");
      const pointerDataDiv = document.getElementById("pointer-data");
      let pointerLngLat = null;
      let hasLabels = false;

      const weatherLayer = new maptilerweatherplus.PressureIsolineLayer({
        opacity: 0.8,
      });

      map.on('load', function () {
        map.setPaintProperty("Water", 'fill-color', "rgba(0, 0, 0, 0.4)");
        map.addLayer(weatherLayer, 'Water');  
      });

      timeSlider.addEventListener("input", (evt) => {
        weatherLayer.setAnimationTime(parseInt(timeSlider.value / 1000));
        hideLabels();
      });

      // 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;
      });

      // Called when the animation is progressing
      weatherLayer.on("tick", event => {
        refreshTime();
        updatePointerValue(pointerLngLat);
      });

      // 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";
          labelsButton.disabled = false;
        } else {
          weatherLayer.animateByFactor(3600);
          playPauseButton.innerText = "Pause";
          hideLabels();
          labelsButton.disabled = true;
        }
        isPlaying = !isPlaying;
      });

      labelsButton.addEventListener("click", () => {
        if (!isPlaying && !hasLabels) {
          weatherLayer.showPressureLabels();
          hasLabels = true;
          labelsButton.innerText = "Hide labels";
        } else {
          hideLabels();
        }
      });

      function hideLabels() {
        weatherLayer.hidePressureLabels();
        hasLabels = false;
        labelsButton.innerText = "Show labels";
      }

      // Update the date time display
      function refreshTime() {
        const d = weatherLayer.getAnimationTimeDate();
        timeTextDiv.innerText = d.toString();
        timeSlider.value = +d;
      }

      map.on('mouseout', function(evt) {
        if (!evt.originalEvent.relatedTarget) {
          pointerDataDiv.innerText = "";
          pointerLngLat = null;
        }
      });

      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)} hPa`
      }

      map.on('mousemove', (e) => {
        updatePointerValue(e.lngLat);
      });

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

## Learn more

Look at the [Weather Plus pressure isolines layer](https://docs.maptiler.com/sdk-js/examples/weather-plus-pressure-isolines/) example

Look at the [Weather Plus pressure isolines layer labels](https://docs.maptiler.com/sdk-js/examples/weather-plus-pressure-isolines-labels/) example

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

Check out the [Pressure Isolines layer reference](https://docs.maptiler.com/sdk-js/modules/weather/api/pressure-isolines/)

## 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+ wind arrow layer](https://docs.maptiler.com/sdk-js/examples/weather-plus-wind-arrow/)

Examples

Visualize wind direction and speed using animated wind arrows.

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

Examples

Display high and low atmospheric pressure extreme value labels.
