@metoceanapi/wxtiles-mbox

WXTiles

This is a project for weather data visualization.

There are two main parts of the project:

  1. Splitter - a service that splits the datasets into tiles (PNG/Webp) and some metadata (JSON). A private project of MetOcean/MetService.
  2. WxTiles-mbox source code, npm @metoceanapi/wxtiles-mbox - a JS API providing work with metadata, dataset manager and an implementation of a Custom MapBox-gl-gs Layer for visualizing the tiles using Mapbox-gl-gs.

Online DOCS

Online Examples

  1. SimpleDemo.
  2. Animated blur parameter
  3. Mouse Interaction and masking

MapBox-gl-js

(async () => {
// MAPBOX initialization START
mapboxgl.accessToken = "--key--";
const map = new mapboxgl.Map({
container: "map",
style: {
version: 8,
name: "Empty",
sources: {},
layers: [],
},
});

map.addControl(new mapboxgl.NavigationControl(), "bottom-right");
await map.once("load");

// WXTILES initialization START
const { WxTilesLogging, WxAPI, CustomWxTilesLayer } = window.wxtilesmbox;
// WxTilesLogging(true); // log WxTiles info to console if needed

const dataServerURL = "https://tilesdev.metoceanapi.com/data/";
const requestInit = {
headers: new Headers({'x-api-key': 'your_key_here'}),
};

// Get the API ready - should be ONE per application
const wxapi = new WxAPI({ dataServerURL, requestInit });

// Define the dataset and variable
const datasetName = "gfs.global";
const variable = "wind.speed.eastward.at-10m"; // Vector example

// Create a dataset manager (may be used for many layers from this dataset)
const wxdatasetManager = await wxapi.createDatasetManager(datasetName);

// Create a layer
const wxsource = wxdatasetManager.createSourceLayer(
{ variable },
{
id: "wxsource",
attribution: "WxTiles",
}
);
map.addSource(wxsource.id, wxsource);
await new Promise((resolve) => map.once("idle", resolve));

// Add wxlayer using CustomWxTilesLayer. Implements GLSL shader for vector field animation
map.addLayer(new CustomWxTilesLayer("wxlayer", wxsource.id), "baseL");
})();

Land Masking And Animated Blur Effect

(async function step(n: number = 0) {
await wxsource.updateCurrentStyleObject({
isolineText: false,
blurRadius: ~~(10 * Math.sin(n / 500) + 10),
}); // await always !!
requestAnimationFrame(step);
})();

Change the Time Step

await wxsource.setTimeStep(1); // 1 - index of the time step in the dataset

or

await wxsource.setTimeStep("2020-01-01T00:00:00Z"); // '2020-01-01T00:00:00Z' - time step in the dataset

or

await wxsource.setTimeStep(2345323454); //  time in seconds since 1970-01-01T00:00:00Z

or

await wxsource.setTimeStep(new Date("2020-01-01T00:00:00Z")); // Date object

Update the Style

await wxsource.updateCurrentStyleObject({ units: "m/s", levels: undefined }); // set levels to undefined - to automatically calculate the levels from the dataset

Preload the Time Steps

// load the time step number 10 to the cache but do not render it
const prom = wxsource.preloadTime(10);
// do stuff asyncronously
// ...
await prom; // wait for the time step to finish loading
// now set the time step to 10
await wxsource.setTime(10); // will be fast rendered from the cache

Abort Loading

const abortController = new AbortController();
console.log("setTime(5)");
const prom = wxsource.setTime(5, abortController);
abortController.abort(); // aborts the request
await prom; // await always !! even if aborted
console.log("aborted");

Get the Current Time Step

const timeStep = wxsource.getTime();

Read Lon Lat Data

map.on("mousemove", (e) => {
if (!wxsource) return;
const pos = position(e); //
const tileInfo: WxTileInfo | undefined = wxsource.getLayerInfoAtLatLon(
pos.wrap(),
map
);
if (tileInfo) {
console.log(tileInfo);
}
});

More Interactive - Additional Level and A Bit of the Red Transparentness Around the Level Made from Current Mouse Position

await wxsource.updateCurrentStyleObject({ levels: undefined }); // reset levels if existing in the style
const levels = wxsource.getCurrentStyleObjectCopy().levels || []; // get current/default/any levels
// generate a new color map from the levels
const colMap: [number, string][] = levels.map((level) => [
level,
"#" + Math.random().toString(16).slice(2, 8) + "ff",
]);
let busy = false;
map.on("mousemove", async (e) => {
if (!wxsource || busy) return;
busy = true;
const tileInfo: WxTileInfo | undefined = wxsource.getLayerInfoAtLatLon(
position(e),
map
);
if (tileInfo) {
await wxsource.updateCurrentStyleObject({
colorMap: [...colMap, [tileInfo.inStyleUnits[0], "#ff000000"]],
});
console.log(tileInfo);
}
busy = false;
});

Legend Usage

The WxCreateLegend function is used to generate a color legend for weather map visualizations. This legend helps represent weather data with corresponding colors, making it easier to interpret the map. Pass the legendSize and style to the WxCreateLegend function to generate the legend. The function returns a WxLegend object containing:

  • size: The number of color steps.
  • colors: A Uint32Array of color values.
  • ticks: An array of WxTick objects representing data points and their corresponding colors.
  • units: The units of the data.
  • showBelowMin / showAboveMax: Whether values outside the range are shown.

Example: Temperature Legend

Here’s an example of creating a temperature legend:

const style: WxColorStyleStrict = {
colorMap: [
[0, "#0000FF"], // blue at 0°C
[15, "#00FF00"], // green at 15°C
[30, "#FF0000"], // red at 30°C
],
showBelowMin: true,
showAboveMax: true,
units: "°C",
fill: "gradient",
};

const legend = WxCreateLegend(100, style);
console.log(legend);

This creates legend with:

  • 100 color steps interpolating between blue, green, and red.
  • Ticks at 0°C, 15°C, and 30°C.
  • Support for values below 0°C and above 30°C.

Color Style

The WxColorStyleStrict interface defines the configuration for styling visualizations. It includes properties for controlling colors, gradients, isolines, vectors, streamlines, and more. Below is a detailed explanation of each property.

Properties

Basic Properties
  • name: The name of the style.
  • parent: The name of a parent style to inherit properties from (optional).
Tile Filling
  • fill: Defines how tiles are filled:
    • "none": No fill, leaves the tile transparent.
    • "solid": Solid fill, no gradient between levels.
    • "gradient": Gradient fill between levels.
Isolines
  • isolineColor: Defines the color of isolines:
    • "none": Do not render isolines.
    • "fill": Use the value of fill for each pixel.
    • "inverted": Use the inverted value of fill for each pixel.
    • #RGB, #RRGGBB, or #RRGGBBAA: Use a specific web color.
  • isolineText: If true, render text values on isolines.
  • isolineTextSizeEm: Font size of isoline text values in em units.
  • isolineTextBackground: If true, render a solid background behind isoline text values.
Vectors (Wind/Current Fields)
  • vectorType: Defines how vectors are represented:
    • "none": Do not render vectors.
    • "arrows": Use arrows to represent winds/currents.
    • "barbs": Use barbs to represent winds/currents.
  • vectorColor: Defines the color of vectors:
    • "none": Do not render vectors.
    • "fill": Use the value of fill for each pixel.
    • "inverted": Use the inverted value of fill for each pixel.
    • #RGB, #RRGGBB, or #RRGGBBAA: Use a specific web color.
  • vectorFactor: Scaling factor for vector length.
Streamlines
  • streamLineColor: Defines the color of streamlines:
    • "none": Do not render streamlines.
    • "fill": Use the value of fill for each pixel.
    • "inverted": Use the inverted value of fill for each pixel.
    • #RGB, #RRGGBB, or #RRGGBBAA: Use a specific web color.
  • streamLineSpeedFactor: Scaling factor for streamline length.
  • streamLineGridStep: Step to seed streamlines. Smaller values create more streamlines.
  • streamLineSteps: Number of steps in each streamline.
  • streamLineStatic: If true, render streamlines as static lines. If false, render as animated lines.
Color Configuration
  • showBelowMin: If true, fill values below the minimum range.
  • showAboveMax: If true, fill values above the maximum range.
  • colorScheme: Name of the color scheme from the default set.
  • colors: Custom array of colors to use for interpolation (optional).
  • colorMap: Array of [level, color] tuples to map specific data values to colors (optional).
  • levels: Array of levels to build the legend. If not provided, 10 levels are calculated evenly based on the data.
Additional Styling
  • blurRadius: Radius for the BOX filter (used for blurring).
  • addDegrees: Additional rotation of wind or current vectors by a specified angle in degrees.
  • units: Units of the style (e.g., °C for temperature).
  • extraUnits: Additional units to extend the default set (optional).
Masking
  • mask: Defines masking behavior:
    • "none": No masking.
    • "sea": Make sea areas transparent.
    • "land": Make land areas transparent.
WebGL Configuration (Optional)
  • gl: Configuration for WebGL rendering:
    • animationSpeed: Speed of animations.
    • noiseTexturePow: Power of noise texture.
    • vectorFieldFactor: Scaling factor for vector fields.
    • animationIntensity: Intensity of animations.
    • wavesCount: Number of waves to render.
Default styles

Default styles can be found here

Generated using TypeDoc