canvas-globe 1.2.0 → 1.4.0
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/CHANGELOG.md +33 -0
- package/README.md +82 -8
- package/codemeta.json +2 -2
- package/custom-elements.json +2 -2
- package/dist/canvas-globe.umd.js +490 -12
- package/package.json +1 -1
- package/src/geo-globe.js +153 -7
- package/src/geo.js +70 -0
- package/src/index.js +1 -0
- package/src/texture.js +39 -4
- package/src/tiles.js +227 -0
- package/src/version.js +1 -1
- package/types/element.d.ts +3 -3
- package/types/index.d.ts +95 -7
- package/types/jsr-element.d.ts +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,39 @@ All notable changes to this package are documented here. The format follows
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.4.0] - 2026-09-19
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Added opt-in cached XYZ overview tiles with Web Mercator conversion, globe and flat-map
|
|
14
|
+
reprojection, provider callbacks, request ceilings, graceful failures, CORS-aware export, and
|
|
15
|
+
attribution painted into every frame.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- Reprojected equirectangular textures correctly in Mercator and Natural Earth map views instead
|
|
20
|
+
of stretching them to the projected viewport.
|
|
21
|
+
|
|
22
|
+
## [1.3.0] - 2026-09-19
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- Added an interactive screen-space hex-bin density layer for globe and map
|
|
27
|
+
modes, including weighted aggregation, colour ramps, source-marker hit
|
|
28
|
+
payloads, framework event types, and 5,000-marker performance coverage.
|
|
29
|
+
- Added an Angular SSR and hydration starter with prerendered HTML, a stable
|
|
30
|
+
canvas shell, client hydration, and project-creator support.
|
|
31
|
+
- Added a reproducible nine-library globe comparison harness for timing,
|
|
32
|
+
bundle size, package metadata, server-import, and accessibility-surface
|
|
33
|
+
measurements.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- Prevented the Angular component from creating a CanvasGlobe instance during
|
|
38
|
+
server rendering.
|
|
39
|
+
- Corrected public TypeScript declarations for story-step overrides and theme
|
|
40
|
+
options.
|
|
41
|
+
|
|
9
42
|
## [1.2.0] - 2026-09-18
|
|
10
43
|
|
|
11
44
|
### Added
|
package/README.md
CHANGED
|
@@ -35,17 +35,19 @@
|
|
|
35
35
|
|
|
36
36
|
[](https://stackblitz.com/github/Shree-hari/canvas-globe?startScript=start)
|
|
37
37
|
|
|
38
|
-
**Start with your stack:** [Vanilla JS](starters/vanilla-vite) | [React + Vite](starters/react-vite) | [Next.js](starters/nextjs-app-router) | [Vue](starters/vue-vite) | [SvelteKit](starters/sveltekit) | [Web Component](starters/web-component-vite)
|
|
38
|
+
**Start with your stack:** [Vanilla JS](starters/vanilla-vite) | [React + Vite](starters/react-vite) | [Next.js](starters/nextjs-app-router) | [Nuxt](starters/nuxt-ssr) | [Vue](starters/vue-vite) | [SvelteKit](starters/sveltekit) | [Angular SSR](starters/angular-ssr) | [Web Component](starters/web-component-vite)
|
|
39
39
|
|
|
40
40
|
**Install with shadcn:** `npx shadcn@latest add https://canvasglobe.swiftools.com/r/canvas-globe.json`
|
|
41
41
|
|
|
42
42
|
`canvas-globe` is a zero-dependency JavaScript library for an interactive
|
|
43
43
|
**3D globe** and **flat world map** on Canvas 2D. It works with
|
|
44
44
|
vanilla JavaScript, React, Vue, Angular, Svelte, or a Web Component and requires no WebGL, map API
|
|
45
|
-
key, tile service, or runtime network request.
|
|
45
|
+
key, tile service, or runtime network request. Optional XYZ tiles are available when you explicitly
|
|
46
|
+
configure a provider.
|
|
46
47
|
|
|
47
|
-
- **Zero dependencies:** no WebGL, D3, map tiles, or API keys
|
|
48
|
-
- **Zero network calls:** country geometry ships inside the package
|
|
48
|
+
- **Zero dependencies:** no required WebGL, D3, map tiles, or API keys
|
|
49
|
+
- **Zero required network calls:** country geometry ships inside the package
|
|
50
|
+
- **Optional XYZ tiles:** opt into a cached raster provider for globe and overview-map backgrounds
|
|
49
51
|
- **Interactive:** drag, zoom, pinch, hover, and click
|
|
50
52
|
- **Marker support:** weighted markers, avatars, pulse rings, and clustering
|
|
51
53
|
- **Great-circle arcs:** animated routes clipped at the horizon
|
|
@@ -139,19 +141,19 @@ your existing application rather than installing a second React copy.
|
|
|
139
141
|
For a plain `<script>` installation, use the versioned UMD build:
|
|
140
142
|
|
|
141
143
|
```html
|
|
142
|
-
<script src="https://cdn.jsdelivr.net/npm/canvas-globe@1.
|
|
144
|
+
<script src="https://cdn.jsdelivr.net/npm/canvas-globe@1.4.0/dist/canvas-globe.umd.js"></script>
|
|
143
145
|
```
|
|
144
146
|
|
|
145
147
|
The same npm release is also available from UNPKG:
|
|
146
148
|
|
|
147
149
|
```html
|
|
148
|
-
<script src="https://unpkg.com/canvas-globe@1.
|
|
150
|
+
<script src="https://unpkg.com/canvas-globe@1.4.0/dist/canvas-globe.umd.js"></script>
|
|
149
151
|
```
|
|
150
152
|
|
|
151
153
|
Modern browsers can import the package through an ESM CDN:
|
|
152
154
|
|
|
153
155
|
```js
|
|
154
|
-
import { createGlobe } from "https://esm.sh/canvas-globe@1.
|
|
156
|
+
import { createGlobe } from "https://esm.sh/canvas-globe@1.4.0";
|
|
155
157
|
```
|
|
156
158
|
|
|
157
159
|
Pin an exact version in production so a future release cannot change a deployed page unexpectedly.
|
|
@@ -171,7 +173,7 @@ import { createGlobe } from "canvas-globe";
|
|
|
171
173
|
Or drop the UMD build on a page with no build step at all:
|
|
172
174
|
|
|
173
175
|
```html
|
|
174
|
-
<script src="https://cdn.jsdelivr.net/npm/canvas-globe@1.
|
|
176
|
+
<script src="https://cdn.jsdelivr.net/npm/canvas-globe@1.4.0/dist/canvas-globe.umd.js"></script>
|
|
175
177
|
<canvas id="globe" style="width:520px;aspect-ratio:1"></canvas>
|
|
176
178
|
<script>
|
|
177
179
|
CanvasGlobe.createGlobe(document.getElementById("globe"), {
|
|
@@ -371,6 +373,7 @@ included effects. See `types/fx.d.ts` for every option and callback signature.
|
|
|
371
373
|
| `orbits` | `0` | Decorative rings: a count (0-6) or explicit specs |
|
|
372
374
|
| `texture` | Not set | Equirectangular image painted onto the sphere |
|
|
373
375
|
| `textureQuality` | `"auto"` | Pixel step for the texture pass; higher is faster |
|
|
376
|
+
| `tileLayer` | Not set | Optional cached XYZ overview tiles; see [Tile layers](#tile-layers) |
|
|
374
377
|
| `focus` | Not set | Frame one country: `"IN"` or `{ country, isolate, dim, outlineWidth }` |
|
|
375
378
|
| `countryMedia` | Not set | Media clipped to each country, keyed by ISO, id or name |
|
|
376
379
|
| `scene` | Not set | Whole composition: preset plus the layers a job needs |
|
|
@@ -381,6 +384,7 @@ included effects. See `types/fx.d.ts` for every option and callback signature.
|
|
|
381
384
|
| `timeline` | Not set | `{ at }`: hides markers whose `date` has not arrived |
|
|
382
385
|
| `transparentBackground` | `false` | Skip the ocean fill so exports keep an alpha channel |
|
|
383
386
|
| `heatmap` | `false` | Additive density blobs: `{ radius, intensity, color }` |
|
|
387
|
+
| `hexBins` | `false` | Interactive screen-space density cells; see [Hex bins](#hex-bins) |
|
|
384
388
|
| `spikes` | `false` | Bars off the surface, sized by `count`: `{ height, width }` |
|
|
385
389
|
| `labels` | `false` | `"markers"` \| `"countries"` \| `"both"`, with collision avoidance |
|
|
386
390
|
| `legend` | Not set | `{ title, items }` or `{ title, scale, position }` |
|
|
@@ -443,6 +447,76 @@ With `cluster: true`, dense areas collapse into a single bubble and your callbac
|
|
|
443
447
|
`{ cluster: true, count, markers, lat, lon }` instead. Clustering happens in screen space, so it
|
|
444
448
|
re-balances automatically as you zoom.
|
|
445
449
|
|
|
450
|
+
## Hex bins
|
|
451
|
+
|
|
452
|
+
Use hex bins when individual markers are too dense to read. CanvasGlobe aggregates the visible,
|
|
453
|
+
projected markers into a pointy-top hexagonal grid, so the density view updates naturally as the
|
|
454
|
+
globe rotates, the map pans, or the user zooms.
|
|
455
|
+
|
|
456
|
+
```js
|
|
457
|
+
const globe = createGlobe(canvas, {
|
|
458
|
+
markers: demandPoints,
|
|
459
|
+
hexBins: {
|
|
460
|
+
radius: 19,
|
|
461
|
+
value: "sum",
|
|
462
|
+
colorRange: ["#dbeafe", "#2563eb", "#172554"],
|
|
463
|
+
padding: 1.5,
|
|
464
|
+
showCount: true,
|
|
465
|
+
},
|
|
466
|
+
tooltip: (target, kind) => kind === "hex-bin"
|
|
467
|
+
? `${target.markerCount} locations, ${target.value} total requests`
|
|
468
|
+
: target.name,
|
|
469
|
+
onClick: (target) => {
|
|
470
|
+
if (target.hexBin) console.log(target.markers);
|
|
471
|
+
},
|
|
472
|
+
});
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
Each interactive bin returned to `tooltip`, `onHover`, and `onClick` contains
|
|
476
|
+
`{ hexBin: true, markerCount, count, value, markers, lat, lon }`. The default `value: "sum"` adds
|
|
477
|
+
each marker's `count`; use `value: "count"` to colour by the number of markers. Individual markers
|
|
478
|
+
are hidden by default while the layer is active. Set `hideMarkers: false` to keep them visible.
|
|
479
|
+
|
|
480
|
+
Available options are `radius`, `minValue`, `value`, `color`, `colorRange`, `opacity`, `stroke`,
|
|
481
|
+
`strokeWidth`, `padding`, `showCount`, `labelColor`, and `hideMarkers`. The same configuration works
|
|
482
|
+
in globe and flat-map modes. Since binning happens after projection, `radius` is measured in screen
|
|
483
|
+
pixels rather than geographic degrees.
|
|
484
|
+
|
|
485
|
+
## Tile layers
|
|
486
|
+
|
|
487
|
+
CanvasGlobe does not contact a tile service by default. Set `tileLayer` only when a raster basemap
|
|
488
|
+
adds real value to the product. The same cached tile mosaic is reprojected for the globe,
|
|
489
|
+
equirectangular, Mercator, and Natural Earth views.
|
|
490
|
+
|
|
491
|
+
```js
|
|
492
|
+
const globe = createGlobe(canvas, {
|
|
493
|
+
tileLayer: {
|
|
494
|
+
url: "https://tiles.example.com/{z}/{x}/{y}.png",
|
|
495
|
+
zoom: 2,
|
|
496
|
+
attribution: "Map data and imagery: Example Maps",
|
|
497
|
+
onError(error, tile) {
|
|
498
|
+
console.warn("Tile unavailable", tile, error);
|
|
499
|
+
},
|
|
500
|
+
},
|
|
501
|
+
});
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
`url` accepts `{z}`, `{x}`, `{y}`, and `{-y}` placeholders. For private, signed, generated, or
|
|
505
|
+
offline imagery, use `getTile({ x, y, z })` and return a URL, canvas, image, bitmap, or a Promise of
|
|
506
|
+
one. Loaded XYZ coordinates are cached for the lifetime of the layer, and failed tiles leave the
|
|
507
|
+
built-in CanvasGlobe background visible instead of breaking the render loop.
|
|
508
|
+
|
|
509
|
+
This is an overview layer, not a slippy-map engine. `zoom` defaults to 2. The default `maxTiles: 64`
|
|
510
|
+
allows up to zoom 3 and prevents a configuration mistake from starting hundreds of requests. Raise
|
|
511
|
+
the ceiling explicitly only when the provider terms, page weight, and device budget allow it.
|
|
512
|
+
|
|
513
|
+
Always supply the attribution required by your provider. CanvasGlobe paints it into the canvas, so
|
|
514
|
+
it remains present in image and video exports. Remote images use anonymous CORS by default because
|
|
515
|
+
globe reprojection and export must read their pixels. The provider must return a compatible
|
|
516
|
+
`Access-Control-Allow-Origin` header. You may set `crossOrigin: null`, but a cross-origin response
|
|
517
|
+
without CORS cannot be reprojected or exported. You are responsible for the provider's licence,
|
|
518
|
+
usage policy, access token, and request limits.
|
|
519
|
+
|
|
446
520
|
### How accurate is marker placement?
|
|
447
521
|
|
|
448
522
|
The projection maths is exact: a marker's pixel position matches the closed-form projection to
|
package/codemeta.json
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
"@type": "SoftwareSourceCode",
|
|
4
4
|
"name": "CanvasGlobe",
|
|
5
5
|
"identifier": "canvas-globe",
|
|
6
|
-
"description": "CanvasGlobe helps developers add interactive 3D globes and flat world maps to JavaScript and React apps with Canvas 2D, without WebGL, map tiles, API keys, or runtime network calls.",
|
|
6
|
+
"description": "CanvasGlobe helps developers add interactive 3D globes and flat world maps to JavaScript and React apps with Canvas 2D, without WebGL, required map tiles, API keys, or required runtime network calls.",
|
|
7
7
|
"url": "https://canvasglobe.swiftools.com/",
|
|
8
|
-
"version": "1.
|
|
8
|
+
"version": "1.4.0",
|
|
9
9
|
"codeRepository": "https://github.com/Shree-hari/canvas-globe",
|
|
10
10
|
"issueTracker": "https://github.com/Shree-hari/canvas-globe/issues",
|
|
11
11
|
"downloadUrl": "https://www.npmjs.com/package/canvas-globe",
|
package/custom-elements.json
CHANGED
|
@@ -112,8 +112,8 @@
|
|
|
112
112
|
{ "name": "lat-range", "description": "Serialized latitude range.", "type": { "text": "[number, number]" } }
|
|
113
113
|
],
|
|
114
114
|
"events": [
|
|
115
|
-
{ "name": "geo-hover", "description": "Fires when the hovered marker changes.", "type": { "text": "CustomEvent<{ marker: Marker | ClusterMarker | null; pos: { x: number; y: number } | null }>" } },
|
|
116
|
-
{ "name": "geo-click", "description": "Fires when a marker is clicked.", "type": { "text": "CustomEvent<{ marker: Marker | ClusterMarker; pos: { x: number; y: number } }>" } },
|
|
115
|
+
{ "name": "geo-hover", "description": "Fires when the hovered marker changes.", "type": { "text": "CustomEvent<{ marker: Marker | ClusterMarker | HexBinMarker | null; pos: { x: number; y: number } | null }>" } },
|
|
116
|
+
{ "name": "geo-click", "description": "Fires when a marker is clicked.", "type": { "text": "CustomEvent<{ marker: Marker | ClusterMarker | HexBinMarker; pos: { x: number; y: number } }>" } },
|
|
117
117
|
{ "name": "geo-country-hover", "description": "Fires when the hovered country changes.", "type": { "text": "CustomEvent<{ country: CountryShape | null; pos: { x: number; y: number } | null }>" } },
|
|
118
118
|
{ "name": "geo-country-click", "description": "Fires when a country is clicked.", "type": { "text": "CustomEvent<{ country: CountryShape; pos: { x: number; y: number } }>" } },
|
|
119
119
|
{ "name": "geo-render", "description": "Fires after CanvasGlobe renders a frame.", "type": { "text": "CustomEvent<{ globe: GeoGlobe }>" } }
|