Skip to content

Commit 2a7a899

Browse files
committed
geo + tip: true
- fix collapsing bug (#1742) - compute a centroid if there is a geometry channel but no x and y channels (#1743)
1 parent e44dd3d commit 2a7a899

File tree

4 files changed

+3208
-12
lines changed

4 files changed

+3208
-12
lines changed

src/plot.js

+13-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {innerDimensions, outerDimensions} from "./scales.js";
1717
import {position, registry as scaleRegistry} from "./scales/index.js";
1818
import {applyInlineStyles, maybeClassName} from "./style.js";
1919
import {initializer} from "./transforms/basic.js";
20+
import {centroidChannels} from "./transforms/centroid.js";
2021
import {consumeWarnings, warn} from "./warnings.js";
2122

2223
export function plot(options = {}) {
@@ -502,8 +503,18 @@ function maybeMarkFacet(mark, topFacetState, options) {
502503
}
503504

504505
function derive(mark, options = {}) {
505-
return initializer({...options, x: null, y: null}, (data, facets, channels, scales, dimensions, context) => {
506-
return context.getMarkState(mark);
506+
return initializer({...options, x: null, y: null}, (da, f, c, s, di, context) => {
507+
let {
508+
data,
509+
facets,
510+
channels: {geometry, x, y, ...channels}
511+
} = context.getMarkState(mark);
512+
if (geometry && !x && !y) {
513+
const {projection} = context;
514+
({x, y} = centroidChannels(data, (d) => d, projection));
515+
if (projection == null) (x.scale = "x"), (y.scale = "y");
516+
}
517+
return {data, facets, channels: {...channels, ...(x && {x}), ...(y && {y})}};
507518
});
508519
}
509520

src/transforms/centroid.js

+16-10
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,23 @@ import {geoCentroid as GeoCentroid, geoPath} from "d3";
22
import {identity, valueof} from "../options.js";
33
import {initializer} from "./basic.js";
44

5-
export function centroid({geometry = identity, ...options} = {}) {
5+
export function centroid({geometry, ...options} = {}) {
66
// Suppress defaults for x and y since they will be computed by the initializer.
7-
return initializer({...options, x: null, y: null}, (data, facets, channels, scales, dimensions, {projection}) => {
8-
const G = valueof(data, geometry);
9-
const n = G.length;
10-
const X = new Float64Array(n);
11-
const Y = new Float64Array(n);
12-
const path = geoPath(projection);
13-
for (let i = 0; i < n; ++i) [X[i], Y[i]] = path.centroid(G[i]);
14-
return {data, facets, channels: {x: {value: X, source: null}, y: {value: Y, source: null}}};
15-
});
7+
return initializer({...options, x: null, y: null}, (data, facets, channels, scales, dimensions, {projection}) => ({
8+
data,
9+
facets,
10+
channels: {...channels, ...centroidChannels(data, geometry, projection)}
11+
}));
12+
}
13+
14+
export function centroidChannels(data, geometry = identity, projection) {
15+
const G = valueof(data, geometry);
16+
const n = G.length;
17+
const X = new Float64Array(n);
18+
const Y = new Float64Array(n);
19+
const path = geoPath(projection);
20+
for (let i = 0; i < n; ++i) [X[i], Y[i]] = path.centroid(G[i]);
21+
return {x: {value: X, source: null}, y: {value: Y, source: null}};
1622
}
1723

1824
export function geoCentroid({geometry = identity, ...options} = {}) {

0 commit comments

Comments
 (0)