Get a UV wind map

In fact, the data is derived from NOAA Grid Grid wind data, the resolution is 1 degree, a total of 360*180 Grid points worldwide (a total of 64,800). As far as I know before, wind data is generally divided into TWO directions, U/V, including NetCDF data. Coordinate information is hidden in the grid index, and wind recorded in two vertical directions, U/V.

The wind force in the horizontal U direction and the wind force in the vertical V direction were respectively taken as R and G values of RGB band, and a PNG was synthesized, as shown in the figure.

Because I did not use the data download API of the official website, I did not get the original JSON data, but only a PNG, so I could not reverse the symbol of U/V value, only positive value. So in the end, only the wind direction in the first quadrant is rendered, which should be fine for demonstration purposes.

TmpCanvas. Width = windimage.width; tmpCanvas.height = windImage.height; tmpCtx.drawImage(windImage, 0, 0); // imageData.data.length: width*height*4let imageData = tmpCtx.getImageData(0, 0, tmpCanvas.width, tmpCanvas.height),
        dataLength = imageData.data.byteLength;
    if(compressRatio == undefined || (compressRatio ! == undefined && compressRatio < 1)) { console.warn("Input compressRatio invalid, use default 1.");
        compressRatio = 1;
    }
for (leti=1; i<tmpCanvas.height-1; i+=compressRatio) { // i:0~180, j:0~360for (letj=0; j<tmpCanvas.width; j+=compressRatio) {let particle = {
                'lon': -180 + j,
                'lat': -90 + i,
            };
            let uIndex = (i * 360 + j) * 4, vIndex = uIndex + 1;
            letUVal = imagedata. data[uIndex], vVal = imagedata. data[vIndex], Math.pow(uVal, 2) + math.pow (vVal, 2), Angle = Number(math.atan (vVal/uVal).tofixed (2)), color = color'rgba('+ (windPow/255).toFixed(0) + ', 255, 100, 0.7);
            // return geojson dataSource for mapboxgl.vector layer.
            if (geojson) {
                particle = { "type": "Feature"."properties": {
                        "angle": angle,
                        "color": color
                    },
                    "geometry": {
                        "type": "Point"."coordinates": [-180 + j, -90 + i]
                    }
                }
                features.push(particle);
            } else{// If you don't use geoJSON data, use a custom canvas for rendering, which is used for animation convenience. particle.angle = angle; particle.radius = radius; particles.push(particle); }}}Copy the code

Canvas Render direction

Once this much has been parsed out, it is time to write the rendering function, which can be rendered using mapBox’s native Fill Layer (webGL-based, more efficient). But for the sake of animation, we will use our animation controller Alex.myTween and CanvasOverLayer extensions to render

// The genWindTarget function simulates the animation effect of a wind particle according to the wind direction, and generates the animation target object, Alex.mytween according tosourceObjs = Windlayer.particles; objs = windlayer.particles; targets = genWindTarget(objs); // calc targets depend on its angle, use 6 degree as dist. Alex.myTween.get(objs).to(targets, 8000, windlayer.redraw); map.on('moveend'.function(){
    windlayer.redraw(objs);
});

Copy the code

The render looks like this:

In fact, it is fun to do. This project originated from the experiment of animation. The API is all ES6 + Webpack. After that, I plan to switch to WebGL, which is more efficient. There are some other plugins in the project, please feel free to play and make issues

Just updated yesterday, chart.js is integrated into the DOM overlay layer of the map, and domOverlay can be directly configured in the plug-in, which is easy to use.

The address of the project: https://github.com/alex2wong/mapbox-plugins

Welcome Star ❤ welcome PR