Weather wind show direction arrow
Witness the awe-inspiring display of the weather wind layer in MapTiler Weather Wind dataset. Explore the wind speed and direction at any desired location by simply following the cursor. Immerse yourself in the captivating wind animation, boasting a remarkable 60 frames per second.
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 { WindLayer } from '@maptiler/weather';
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;
config.apiKey = 'YOUR_MAPTILER_API_KEY_HERE';
const map = new Map({
container: document.getElementById('map'),
hash: true,
zoom: 2,
center: [0, 40],
style: MapStyle.BACKDROP,
projectionControl: true
});
const layer = new WindLayer();
map.on('load', function () {
// Darkening the water layer to make the land stand out
map.setPaintProperty("Water", 'fill-color', "rgba(0, 0, 0, 0.4)");
map.addLayer(layer, 'Water');
});
timeSlider.addEventListener("input", (evt) => {
layer.setAnimationTime(parseInt(timeSlider.value / 1000))
})
// 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.
layer.on("sourceReady", event => {
const startDate = layer.getAnimationStartDate();
const endDate = layer.getAnimationEndDate();
const currentDate = layer.getAnimationTimeDate();
refreshTime()
timeSlider.min = +startDate;
timeSlider.max = +endDate;
timeSlider.value = +currentDate;
})
// Called when the animation is progressing
layer.on("tick", event => {
refreshTime();
updatePointerValue(pointerLngLat);
})
// Called when the time is manually set
layer.on("animationTimeSet", event => {
refreshTime()
})
// When clicking on the play/pause
let isPlaying = false;
playPauseButton.addEventListener("click", () => {
if (isPlaying) {
layer.animateByFactor(0);
playPauseButton.innerText = "Play 3600x";
} else {
layer.animateByFactor(3600);
playPauseButton.innerText = "Pause";
}
isPlaying = !isPlaying;
})
// Update the date time display
function refreshTime() {
const d = layer.getAnimationTimeDate();
timeTextDiv.innerText = d.toString();
timeSlider.value = +d;
}
function updatePointerValue(lngLat) {
if (!lngLat) return;
pointerLngLat = lngLat;
const value = layer.pickAt(lngLat.lng, lngLat.lat);
if (!value) {
pointerDataDiv.innerText = "";
return;
}
pointerDataDiv.innerHTML = `<div id="arrow" style="transform: rotate(${value.directionAngle}deg);">↑</div>
${value.compassDirection} ${value.speedKilometersPerHour.toFixed(1)} km/h`;
}
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>Display a wind layer direction</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="time-info">
<span id="time-text"></span>
<button id="play-pause-bt">Play 3600x</button>
<input type="range" id="time-slider" min="0" max="11" step="1">
</div>
<div id="variable-name">Wind</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: #333359; }
#time-info {
position: fixed;
width: 60vw;
bottom: 0;
z-index: 1;
margin: 10px;
text-shadow: 0px 0px 5px black;
color: white;
font-size: 20px;
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;
}
#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;
display: inline-flex;
align-items: center;
}
#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;
}
#arrow {
width: fit-content;
height: fit-content;
background: #fff;
color: #000;;
width: 20px;
font-size: 20px;
height: 20px;
text-align: center;
line-height: 20px;
padding: 5px;
border-radius: 50%;
margin: 0px 10px;
border: dotted red 5px;
}
Learn more
Check out the Weather JS module reference
Check out the Wind layer reference
Related examples
Weather custom popup
ExamplesCreate highly customizable popups for weather maps using MarkerLayout.