Skip to content

Determine the default height when the projection domain is set #2102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/dimensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ function autoHeight(
) {
const nfy = fy ? fy.scale.domain().length : 1;

// If a projection is specified, use its natural aspect ratio (if known).
// If a projection is specified, compute an aspect ratio based on the domain,
// defaulting to the projection’s natural aspect ratio (if known).
const ar = projectionAspectRatio(projection);
if (ar) {
const nfx = fx ? fx.scale.domain().length : 1;
Expand Down
33 changes: 22 additions & 11 deletions src/projection.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,10 @@ function scaleProjection(createProjection, kx, ky) {
if (precision != null) projection.precision?.(precision);
if (rotate != null) projection.rotate?.(rotate);
if (typeof clip === "number") projection.clipAngle?.(clip);
projection.scale(Math.min(width / kx, height / ky));
projection.translate([width / 2, height / 2]);
if (width != null) {
projection.scale(Math.min(width / kx, height / ky));
projection.translate([width / 2, height / 2]);
}
return projection;
},
aspectRatio: ky / kx
Expand All @@ -183,7 +185,7 @@ function conicProjection(createProjection, kx, ky) {
const projection = type(options);
if (parallels != null) {
projection.parallels(parallels);
if (domain === undefined) {
if (domain === undefined && width != null) {
projection.fitSize([width, height], {type: "Sphere"});
}
}
Expand Down Expand Up @@ -234,16 +236,25 @@ export function hasProjection({projection} = {}) {
return projection != null;
}

// When a named projection is specified, we can use its natural aspect ratio to
// determine a good value for the projection’s height based on the desired
// width. When we don’t have a way to know, the golden ratio is our best guess.
// Due to a circular dependency (we need to know the height before we can
// construct the projection), we have to test the raw projection option rather
// than the materialized projection; therefore we must be extremely careful that
// the logic of this function exactly matches createProjection above!
// When a projection is specified, we can use its aspect ratio to determine a
// good value for the projection’s height based on the desired width. When we
// don’t have a way to know, the golden ratio is our best guess. Due to a
// circular dependency (we need to know the height before we can construct the
// projection), we have to test the raw projection option rather than the
// materialized projection; therefore we must be extremely careful that the
// logic of this function exactly matches createProjection above!
export function projectionAspectRatio(projection) {
if (typeof projection?.stream === "function") return defaultAspectRatio;
if (isObject(projection)) projection = projection.type;
if (isObject(projection)) {
let domain, options;
({domain, type: projection, ...options} = projection);
if (domain != null && projection != null) {
const type = typeof projection === "string" ? namedProjection(projection).type : projection;
const [[x0, y0], [x1, y1]] = geoPath(type({...options, width: 100, height: 100})).bounds(domain);
const r = (y1 - y0) / (x1 - x0);
return r && isFinite(r) ? (r < 0.2 ? 0.2 : r > 5 ? 5 : r) : defaultAspectRatio;
}
}
if (projection == null) return;
if (typeof projection !== "function") {
const {aspectRatio} = namedProjection(projection);
Expand Down
134 changes: 67 additions & 67 deletions test/output/geoText.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
208 changes: 104 additions & 104 deletions test/output/geoTip.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
208 changes: 104 additions & 104 deletions test/output/geoTipCentroid.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
208 changes: 104 additions & 104 deletions test/output/geoTipGeoCentroid.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
208 changes: 104 additions & 104 deletions test/output/geoTipXY.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions test/output/projectionDomainRatioME.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading