layerchart 2.0.0-next.52 → 2.0.0-next.53

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.
@@ -84,6 +84,18 @@
84
84
  */
85
85
  referencePoint?: [number, number];
86
86
 
87
+ /**
88
+ * Scale of the projection originally used to pre-project the data, for
89
+ * charts that render pre-projected topologies via `geoIdentity`. For
90
+ * example, the `us-atlas` `counties-albers-10m` / `states-albers-10m`
91
+ * topologies are pre-projected with `geoAlbersUsa().scale(1300)`, so pass
92
+ * `referenceScale={1300}`. When provided, pixels-per-distance is derived
93
+ * directly from the chart's `geoIdentity` fit scale and this reference
94
+ * scale, bypassing the `projection.invert` + `geoDistance` path which
95
+ * does not work for pre-projected data.
96
+ */
97
+ referenceScale?: number;
98
+
87
99
  /**
88
100
  * The placement of the legend.
89
101
  */
@@ -141,6 +153,7 @@
141
153
  height = 4,
142
154
  title = '',
143
155
  referencePoint,
156
+ referenceScale,
144
157
  placement,
145
158
  color = 'currentColor',
146
159
  classes = {},
@@ -163,19 +176,37 @@
163
176
  // `null` if no projection or invert is unavailable (or numerically degenerate).
164
177
  const pixelsPerUnit = $derived.by(() => {
165
178
  const projection = ctx.geo?.projection;
166
- if (!projection || typeof projection.invert !== 'function') return null;
167
-
168
- const refPx: [number, number] = referencePoint ?? [ctx.width / 2, ctx.height / 2];
169
- const a = projection.invert(refPx);
170
- const b = projection.invert([refPx[0] + 1, refPx[1]]);
171
- if (!a || !b) return null;
172
- if (!Number.isFinite(a[0]) || !Number.isFinite(b[0])) return null;
173
-
174
- const radiansPerPx = geoDistance(a, b);
175
- if (!Number.isFinite(radiansPerPx) || radiansPerPx === 0) return null;
176
-
177
- const unitsPerPx = radiansPerPx * earthRadius;
178
- let pxPerUnit = 1 / unitsPerPx;
179
+ if (!projection) return null;
180
+
181
+ let pxPerUnit: number;
182
+
183
+ if (referenceScale != null) {
184
+ // Pre-projected data path (e.g. `geoIdentity` + us-atlas
185
+ // `counties-albers-10m`): `projection.invert` returns topology pixel
186
+ // coordinates, not lon/lat, so `geoDistance` can't be used. Instead,
187
+ // combine the chart's fit scale with the known base projection scale:
188
+ // topology units per chart px = 1 / fitScale
189
+ // radians per topology unit = 1 / referenceScale
190
+ // units (mi/km) per radian = earthRadius
191
+ // => px per unit = (fitScale * referenceScale) / earthRadius
192
+ const fitScale = typeof projection.scale === 'function' ? projection.scale() : null;
193
+ if (fitScale == null || !Number.isFinite(fitScale) || fitScale === 0) return null;
194
+ pxPerUnit = (fitScale * referenceScale) / earthRadius;
195
+ } else {
196
+ if (typeof projection.invert !== 'function') return null;
197
+
198
+ const refPx: [number, number] = referencePoint ?? [ctx.width / 2, ctx.height / 2];
199
+ const a = projection.invert(refPx);
200
+ const b = projection.invert([refPx[0] + 1, refPx[1]]);
201
+ if (!a || !b) return null;
202
+ if (!Number.isFinite(a[0]) || !Number.isFinite(b[0])) return null;
203
+
204
+ const radiansPerPx = geoDistance(a, b);
205
+ if (!Number.isFinite(radiansPerPx) || radiansPerPx === 0) return null;
206
+
207
+ const unitsPerPx = radiansPerPx * earthRadius;
208
+ pxPerUnit = 1 / unitsPerPx;
209
+ }
179
210
 
180
211
  // In `canvas` transform mode the projection itself is not re-scaled — the
181
212
  // rendered output is visually scaled by `ctx.transform.scale`, so we need
@@ -69,6 +69,17 @@ export type GeoLegendPropsWithoutHTML = {
69
69
  * area, which is generally a reasonable approximation away from the poles.
70
70
  */
71
71
  referencePoint?: [number, number];
72
+ /**
73
+ * Scale of the projection originally used to pre-project the data, for
74
+ * charts that render pre-projected topologies via `geoIdentity`. For
75
+ * example, the `us-atlas` `counties-albers-10m` / `states-albers-10m`
76
+ * topologies are pre-projected with `geoAlbersUsa().scale(1300)`, so pass
77
+ * `referenceScale={1300}`. When provided, pixels-per-distance is derived
78
+ * directly from the chart's `geoIdentity` fit scale and this reference
79
+ * scale, bypassing the `projection.invert` + `geoDistance` path which
80
+ * does not work for pre-projected data.
81
+ */
82
+ referenceScale?: number;
72
83
  /**
73
84
  * The placement of the legend.
74
85
  */
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "license": "MIT",
6
6
  "repository": "techniq/layerchart",
7
7
  "homepage": "https://layerchart.com",
8
- "version": "2.0.0-next.52",
8
+ "version": "2.0.0-next.53",
9
9
  "devDependencies": {
10
10
  "@changesets/cli": "^2.30.0",
11
11
  "@napi-rs/canvas": "^0.1.97",