geo-morpher 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -44
- package/data/winchester/winchester_lsoa_cartogram.geojson +3245 -0
- package/data/winchester/winchester_lsoa_geo.geojson +24263 -0
- package/data/winchester/winchester_msoa_cartogram.geojson +635 -0
- package/data/winchester/winchester_msoa_geo.geojson +10743 -0
- package/data/winchester/winchester_ward_cartogram.geojson +725 -0
- package/data/winchester/winchester_ward_geo.geojson +10087 -0
- package/examples/README.md +2 -0
- package/examples/leaflet/canvas-glyphs.html +44 -0
- package/examples/leaflet/canvas-main.js +208 -0
- package/examples/leaflet/index.html +13 -10
- package/examples/leaflet/main.js +83 -20
- package/examples/leaflet/zoom-scaling-glyphs.html +1 -0
- package/examples/maplibre/index.html +3 -3
- package/examples/maplibre/indonesia/index.html +164 -144
- package/examples/maplibre/indonesia/main.js +397 -131
- package/examples/maplibre/main.js +3 -21
- package/examples/winchester/index.html +294 -0
- package/examples/winchester/main.js +333 -0
- package/examples/winchester/winchester_example.md +145 -0
- package/package.json +3 -4
- package/src/adapters/leaflet/glyphLayer.js +23 -9
- package/src/adapters/leaflet/index.js +3 -1
- package/src/adapters/leaflet/utils/collections.js +3 -37
- package/src/adapters/leaflet/utils/coordinates.js +1 -5
- package/src/adapters/leaflet/utils/glyphNormalizer.js +19 -74
- package/src/adapters/maplibre/glyphLayer.js +21 -10
- package/src/adapters/maplibre/index.js +2 -0
- package/src/adapters/maplibre/morphLayers.js +6 -5
- package/src/adapters/maplibre/utils/coordinates.js +2 -26
- package/src/adapters/maplibre/utils/customGlyphLayer.js +485 -0
- package/src/adapters/maplibre/utils/glyphNormalizer.js +14 -117
- package/src/adapters/shared/collections.js +27 -0
- package/src/adapters/shared/dom.js +6 -0
- package/src/adapters/shared/geometry.js +26 -0
- package/src/adapters/shared/glyphNormalizer.js +103 -0
- package/src/adapters/shared/markerAdapter.js +64 -0
- package/src/core/geomorpher.js +95 -8
- package/src/index.js +6 -2
- package/src/utils/projections.js +34 -16
- package/morphs.js +0 -1
package/README.md
CHANGED
|
@@ -7,10 +7,16 @@ GeoJSON morphing utilities for animating between regular geography and cartogram
|
|
|
7
7
|
|
|
8
8
|

|
|
9
9
|
|
|
10
|
+
To quickly create a grid cartogram, checkout my other library: .
|
|
10
11
|
|
|
11
|
-
## Status
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **MapLibre & Leaflet Adapters**: High-performance MapLibre-first implementation with Leaflet compatibility helpers.
|
|
16
|
+
- **Generic Morphing Engine**: Smoothly interpolates between any two aligned GeoJSON geometries using `flubber`.
|
|
17
|
+
- **Multivariate Glyphs**: Highly customizable DOM/SVG/Canvas overlays (charts, icons, sparklines) that stay synced with morphing geometry.
|
|
18
|
+
- **Basemap Effects**: Synchronized fading, blurring, or grayscale effects for basemap layers during transitions.
|
|
19
|
+
- **Projection Agnostic**: Auto-detects WGS84 (lat/lng) data; defaults to OSGB (British National Grid) for UK data but supports any CRS via `proj4`.
|
|
14
20
|
|
|
15
21
|
|
|
16
22
|
## Installation
|
|
@@ -19,30 +25,16 @@ This library is currently in early-stage development (v0.1.0) and has recently c
|
|
|
19
25
|
npm install geo-morpher
|
|
20
26
|
```
|
|
21
27
|
|
|
22
|
-
|
|
28
|
+
Leaflet is provided as a peer dependency—bring your own Leaflet instance when using the compatibility helpers. MapLibre remains the default adapter and is bundled as a dependency for out-of-the-box usage; if your build already supplies `maplibre-gl`, mark it as external to avoid duplicating the library.
|
|
23
29
|
|
|
24
30
|
## Usage
|
|
25
31
|
|
|
26
|
-
Project structure highlights:
|
|
27
|
-
|
|
28
|
-
```text
|
|
29
|
-
src/
|
|
30
|
-
core/ # GeoMorpher core engine
|
|
31
|
-
adapters/ # Integration helpers (Leaflet, etc.)
|
|
32
|
-
lib/ # Shared runtime utilities (OSGB projection)
|
|
33
|
-
utils/ # Data enrichment and projection helpers
|
|
34
|
-
data/ # Sample Oxford LSOA datasets
|
|
35
|
-
examples/ # Runnable browser demos (MapLibre & Leaflet)
|
|
36
|
-
test/ # node:test coverage for core behaviours
|
|
37
|
-
```
|
|
38
|
-
|
|
39
32
|
### MapLibre adapter (default)
|
|
40
33
|
|
|
41
34
|
- `createMapLibreMorphLayers` provisions GeoJSON sources and fill layers for regular, cartogram, and interpolated geometries, exposing an `updateMorphFactor` helper to drive tweening from UI controls.
|
|
42
35
|
- `createMapLibreGlyphLayer` renders glyphs with `maplibregl.Marker` instances; enable `scaleWithZoom` to regenerate glyph markup as users zoom.
|
|
43
36
|
- Pass your MapLibre namespace explicitly (`maplibreNamespace: maplibregl`) when calling glyph helpers in module-bundled builds where `maplibregl` is not attached to `globalThis`.
|
|
44
37
|
- For heavy glyph scenes, consider upgrading to a [CustomLayerInterface](https://www.maplibre.org/maplibre-gl-js/docs/API/interfaces/CustomLayerInterface/) implementation that batches drawing on the GPU. The marker pipeline keeps the API simple while offering a documented migration path.
|
|
45
|
-
- Track ongoing enhancements and open items in `docs/maplibre-migration-plan.md` before relying on the adapter in production.
|
|
46
38
|
|
|
47
39
|
#### MapLibre basemap effects
|
|
48
40
|
|
|
@@ -103,39 +95,27 @@ const cartogram = morpher.getCartogramFeatureCollection();
|
|
|
103
95
|
const tween = morpher.getInterpolatedFeatureCollection(0.5);
|
|
104
96
|
```
|
|
105
97
|
|
|
106
|
-
####
|
|
98
|
+
#### Projections & Coordinate Systems
|
|
107
99
|
|
|
108
|
-
|
|
100
|
+
While `geo-morpher` was born out of UK-centric cartography, it is fully generic. It internally projects all data to WGS84 (latitude/longitude) for mapping compatibility.
|
|
101
|
+
|
|
102
|
+
- **Auto-detection**: If no projection is provided, `GeoMorpher` inspects your coordinates. If they look like WGS84, it uses them as-is.
|
|
103
|
+
- **OSGB Default**: If coordinates fall outside the geographic range, it assumes OSGB (EPSG:27700) and transforms them to WGS84.
|
|
104
|
+
- **Manual Override**: Pass a helper like `WebMercatorProjection` or a custom `proj4` wrapper for other systems.
|
|
109
105
|
|
|
110
106
|
```js
|
|
111
|
-
import { GeoMorpher, WGS84Projection,
|
|
107
|
+
import { GeoMorpher, WGS84Projection, createProj4Projection } from "geo-morpher";
|
|
108
|
+
import proj4 from "proj4";
|
|
112
109
|
|
|
113
|
-
// Auto-
|
|
114
|
-
const
|
|
115
|
-
console.log("Detected:", detectedProjection); // 'WGS84', 'OSGB', or 'UNKNOWN'
|
|
110
|
+
// 1. Auto-detected (usually works for WGS84 or OSGB)
|
|
111
|
+
const morpher = new GeoMorpher({ regularGeoJSON, cartogramGeoJSON });
|
|
116
112
|
|
|
117
|
-
//
|
|
118
|
-
const morpher = new GeoMorpher({
|
|
119
|
-
regularGeoJSON,
|
|
120
|
-
cartogramGeoJSON,
|
|
121
|
-
projection: WGS84Projection, // No transformation needed
|
|
122
|
-
});
|
|
113
|
+
// 2. Explicit WGS84 (Identity)
|
|
114
|
+
const morpher = new GeoMorpher({ ..., projection: WGS84Projection });
|
|
123
115
|
|
|
124
|
-
//
|
|
125
|
-
|
|
126
|
-
const morpher = new GeoMorpher({
|
|
127
|
-
regularGeoJSON,
|
|
128
|
-
cartogramGeoJSON,
|
|
129
|
-
projection: WebMercatorProjection,
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
// Custom projection (e.g., using proj4)
|
|
133
|
-
const customProjection = {
|
|
134
|
-
toGeo: ([x, y]) => {
|
|
135
|
-
// Transform [x, y] to [lng, lat]
|
|
136
|
-
return [lng, lat];
|
|
137
|
-
}
|
|
138
|
-
};
|
|
116
|
+
// 3. Custom Projection (e.g., UTM Zone 33N)
|
|
117
|
+
const projection = createProj4Projection("+proj=utm +zone=33 +datum=WGS84", proj4);
|
|
118
|
+
const morpher = new GeoMorpher({ ..., projection });
|
|
139
119
|
```
|
|
140
120
|
|
|
141
121
|
See `examples/maplibre/projections/index.html` for a browser-based custom projection demo.
|
|
@@ -241,6 +221,24 @@ slider.addEventListener("input", (event) => {
|
|
|
241
221
|
updateMorphFactor(value);
|
|
242
222
|
glyphLayer.updateGlyphs({ morphFactor: value });
|
|
243
223
|
});
|
|
224
|
+
|
|
225
|
+
// You can also decouple glyphs from the GeoMorpher by providing a
|
|
226
|
+
// `featureCollection` or a live `featureProvider({ geometry, morphFactor })`:
|
|
227
|
+
//
|
|
228
|
+
// const glyph = await createLeafletGlyphLayer({
|
|
229
|
+
// drawGlyph,
|
|
230
|
+
// L,
|
|
231
|
+
// featureCollection: morpher.getRegularFeatureCollection(), // static set
|
|
232
|
+
// });
|
|
233
|
+
//
|
|
234
|
+
// const glyphProvider = await createLeafletGlyphLayer({
|
|
235
|
+
// drawGlyph,
|
|
236
|
+
// L,
|
|
237
|
+
// featureProvider: ({ geometry, morphFactor }) => morpher.getInterpolatedFeatureCollection(morphFactor),
|
|
238
|
+
// });
|
|
239
|
+
//
|
|
240
|
+
// The adapters also export small helper functions to convert normalized glyph values
|
|
241
|
+
// into platform-specific objects: `createLeafletIcon` and `createMapLibreMarkerData`.
|
|
244
242
|
```
|
|
245
243
|
|
|
246
244
|
`drawGlyph` receives `{ feature, featureId, data, morpher, geometry, morphFactor }` and can return:
|
|
@@ -487,6 +485,10 @@ Run the bundled smoke tests with:
|
|
|
487
485
|
npm test
|
|
488
486
|
```
|
|
489
487
|
|
|
488
|
+
## Author
|
|
489
|
+
|
|
490
|
+
Dany Laksono
|
|
491
|
+
|
|
490
492
|
## License
|
|
491
493
|
|
|
492
494
|
MIT
|