<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>Transposed multidimensional ImageryTileLayer | Sample | ArcGIS Maps SDK for JavaScript</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.0.0-alpha/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/underscore@1.13.1/underscore-umd-min.js"></script>
<link rel="stylesheet" href="https://js.arcgis.com/5.0/esri/themes/light/main.css" />
<!-- Load the ArcGIS Maps SDK for JavaScript from CDN -->
<script type="module" src="https://js.arcgis.com/5.0/"></script>
const [Map, MapView, ImageryTileLayer, Legend, TimeSlider, Expand] = await $arcgis.import([
"@arcgis/core/views/MapView.js",
"@arcgis/core/layers/ImageryTileLayer.js",
"@arcgis/core/widgets/Legend.js",
"@arcgis/core/widgets/TimeSlider.js",
"@arcgis/core/widgets/Expand.js",
// create a new instance of an imagery tile layer and apply
// VectorFieldRenderer to show the speed and direction of wind
const layer = new ImageryTileLayer({
url: "https://tiledimageservices.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/NLDAS2011_daily_wind_magdir/ImageServer",
title: "2011 wind - 10 meters above surface",
style: "beaufort-m", // Beaufort point symbol (meters)
flowRepresentation: "flow-to",
field: "Magnitude", // values read from the first band
field: "Direction", // values read from the second band
rotationType: "geographic", // "arithmetic" is the default
basemap: "dark-gray-vector",
const view = new MapView({
// add the wind rose chart div
const infoDiv = document.getElementById("infoDiv");
const infoDivExpand = new Expand({
expandTooltip: "Wind rose chart",
view.ui.add(infoDivExpand, "top-right");
view.whenLayerView(layer).then(() => {
// get all the time dimension values from the service and create an array of dates
layer.serviceRasterInfo.multidimensionalInfo.variables[0].dimensions[0].values;
const windDates = windEpochDates.map((item) => new Date(item));
// time slider widget initialization
// users can visualize daily wind information for all the time dimension available
const timeSlider = new TimeSlider({
start: new Date(windDates[0]), // Jan 1, 2011,
end: new Date(windDates[windDates.length - 1]), // Dec 31, 2011
// set the stops to match the dates coming from time dimension
const timeSliderExpand = new Expand({
expandTooltip: "TimeSlider",
content: timeSlider.container,
view.ui.add(timeSliderExpand, "bottom-left");
// Get wind direction and speed info for all the time dimension values available from this
// transposed multidimensional service - identify will return 365 values for the each day of 2011
view.on("click", (event) => getWindSamples(view.toMap(event)));
async function getWindSamples(currentLocation) {
if (layer.serviceRasterInfo.hasMultidimensionalTranspose) {
// set the transposedVariableName for the identify method. Identify method will return
// values for all the slices since multidimensionalDefinition is not defined
const results = await layer.identify(currentLocation, {
transposedVariableName: "wind_magdir",
if (!results.dataSeries) {
// first number is the magdirValue array is the wind magnitude
// second number is the magdirValue array is the direction the wind blew from.
const pixelValues = results.dataSeries.map(({ magdirValue }) => [
const data = getFrequencies(pixelValues);
document.getElementById("instructionsDiv").style.display = "none";
// The layer is displaying the wind data in beaufort meters.
// Create wind rose chart based on the layer legend
// https://en.wikipedia.org/wiki/Beaufort_scale
// https://www.weather.gov/mfl/beaufort
const forces = [0.2, 1.8, 3.3, 5.4, 8.5, 11, 14.1, 17.2, 20.8, 24.4, 28.6, 32.7];
const backgroundColor = [
"rgb(101,137,184)", //1.8
"rgb(132,158,186)", //3.3
"rgb(162,180,189)", //5.4
"rgb(192,204,190)", //8.5
"rgb(255,255,191)", //14.1
"rgb(255,220,161)", //17.2
"rgb(245,152,105)", //20.8
"rgb(237,117,81)", //24.4
"rgb(237,117,81)", //28.6
// this function calculates the percentage of different wind speeds (12 beaufort scales) flew
// from 16 different directions.
function getFrequencies(data) {
const segmentAngle = 360 / segments;
let windSpeedFrequency = [];
for (let i = 0; i < segments; i++) {
windSpeedFrequency[i] = new Float32Array(12);
// get the beaufort scale meters per second
let getBeaufortScale = function (windSpeed) {
for (let i = 0; i < 12; i++) {
if (forces[i] >= windSpeed) {
// loop through wind data and set the beaufort wind scale
for (let i = 0; i < total; i++) {
let monthData = data[i]; // this data returns wind data for each month for given years
let direction = monthData[1];
// check the given direction and identify which sector it belongs to the chart
let directionSegment = Math.round((direction + segmentAngle / 2) / segmentAngle);
if (directionSegment >= segments) {
directionSegment = segments - 1;
const windScale = getBeaufortScale(monthData[0]);
windSpeedFrequency[directionSegment][windScale]++;
// prep the wind rose chart data for the polarArea chart
const transposed = _.zip.apply(_, windSpeedFrequency);
function drawChart(data) {
data.forEach((item, i) => {
backgroundColor: backgroundColor[i],
const ctx = document.getElementById("windRose-chart").getContext("2d");
windRoseChart = new Chart(ctx, {
// shows border for angle/sector lines
stacked: true, // stack the bars
callback: (value, data) => {
const percent = Math.round((value * 100) / 365);
label: (tooltipItem, data) => {
var label = data.datasets[tooltipItem.datasetIndex].label || "";
label += Math.round((tooltipItem.value * 100) / 365) + "%";
windRoseChart.data.datasets = [];
windRoseChart.data.datasets = dataset;
// add a legend for the wind direction and speed layer
const legendExpand = new Expand({
view.ui.add(legendExpand, "top-left");
<div id="infoDiv" class="esri-widget">
<h4 class="esri-widget__heading esri-editor__title">Wind Rose Chart</h4>
<div class="esri-widget">
Daily average wind direction and speed between 1/1/2011 - 12/31/2011
<div id="instructionsDiv" class="esri-widget">
<h5 class="esri-widget__heading esri-editor__title">Instructions:</h5>
<p>Data displays daily average wind direction and speed as recorded on Jan 1, 2011.</p>
<p>Use the time slider to animate through time.</p>
Click on the wind directions data on the map to see the general wind direction (blew-from)
and speed (m/s) for each day of 2011. <br /><br />Learn more about
href="https://www.epa.gov/sites/default/files/2019-01/documents/how_to_read_a_wind_rose.pdf"
<canvas id="windRose-chart" height="300" width="300" class="esri-widget"></canvas>
<div id="timeSlider"></div>