@softwarity/sigwx-draw
v1.2.0
Published
Draw SIGWX (significant weather) charts on any map (grafts onto MapLibre, OpenLayers or Leaflet, Terra-Draw-style). Phenomenon-driven geometry whose metadata controls the rendering (jet barbs, scalloped CB, dashed turbulence, …).
Readme
@softwarity/sigwx-draw
Works with (via @softwarity/draw-adapter)
Headless SIGWX (significant weather) chart editor that grafts onto an existing
MapLibre GL, OpenLayers or Leaflet map — the sibling of
@softwarity/sigmet-draw. The host owns the map; this library
adds the drawing overlays, edit handles and a phenomenon-driven metadata model.
The three engines render identically: the map layer is the shared, data-driven
@softwarity/draw-adapter, so styling lives in the data and no
domain type ever reaches the engine.
The defining idea: a phenomenon's metadata drives its rendering. A jet
stream's wind barbs are computed from its maxWindSpeed; a CB gets a scalloped
edge and an ISOL/OCNL/FRQ label; turbulence gets a dashed outline and a MOD/SEV
glyph. Each phenomenon is a self-contained, data-driven PhenomenonDef in a
registry, so adding one never touches the controller.
Status: v1 demonstrator —
jetStream,cb,turbulence. The architecture (registry + decoration pipeline + layer manifest + schema-driven form) is built so the remaining phenomena (icing, fronts, tropopause, tropical cyclone, volcanic ash, …) plug in as newPhenomenonDefs.
Install
npm i @softwarity/sigwx-draw
# peer deps (only the engine you use):
npm i maplibre-gl # and/or ol and/or leafletQuick start (MapLibre)
import { SigwxDraw } from "@softwarity/sigwx-draw";
import { MapLibreAdapter, createMapLibreMap } from "@softwarity/sigwx-draw/maplibre";
import { registerSigwxMetadataForm } from "@softwarity/sigwx-draw/form";
const map = createMapLibreMap({ container: "map", center: [2.3, 46.6], zoom: 5 });
const sigwx = new SigwxDraw({ adapter: new MapLibreAdapter({ map }), toolbar: true });
// Drive the metadata form (optional convenience web component):
registerSigwxMetadataForm();
const form = document.querySelector("sigwx-metadata-form");
sigwx.on("select", (spec) => (form.spec = spec)); // selection changed
sigwx.on("metadata", (spec) => (form.spec = spec)); // values/visibility/errors
form.addEventListener("change", (e) =>
sigwx.updateMetadata(e.detail.featureId, { [e.detail.key]: e.detail.value }),
);
sigwx.on("change", (geojson) => console.log(geojson)); // FeatureCollection outputOpenLayers is identical via @softwarity/sigwx-draw/openlayers
(OpenLayersAdapter / createOpenLayersMap), and Leaflet via
@softwarity/sigwx-draw/leaflet (LeafletAdapter / createLeafletMap, an L.Map).
The consumer loads the engine's stylesheet (maplibre-gl/dist/maplibre-gl.css,
ol/ol.css, or leaflet/dist/leaflet.css). Each engine is an optional
peerDependency — install only the one(s) you use. Capabilities differ: the globe
projection is MapLibre-only (OpenLayers & Leaflet are 2D).
API
new SigwxDraw({ adapter, registry?, style?, toolbar?, symbolSprite?, phenomena?, turbulenceTypes? })draw(type) → id(enter draw mode),select(id|null),updateMetadata(id, patch),updateListItem(id, list, i, patch),removeListItem(id, list, i),delete(id),clear(),bringToFront(id),sendToBack(id)save(): FeatureCollection,load(fc)— metadata lives in featurepropertieson("change" | "select" | "metadata", cb),off(...),ready(),destroy()setStyle(partial),setPhenomenonStyle(type, style),setPhenomenonFlightLevel(type, { min, max }),addTurbulenceTypes(types)
Headless core (no map)
@softwarity/sigwx-draw/core exposes the pure pieces — the PhenomenonRegistry,
the metadata schema/validation, the decoration generators (barbCounts,
windBarbFeatures, scallopRing, …) and the GeoJSON (de)serialization. All
unit-testable without a map.
Develop
npm run build # tsc → dist (ESM + d.ts)
npm test # vitest (pure core + controller via a mock adapter)
cd demo && npm start # Angular demo at http://localhost:4211 (MapLibre + OpenLayers + Leaflet)