Skip to content

Commit 1f79087

Browse files
authored
tip should ignore p[xy] (#1562)
1 parent ca565a5 commit 1f79087

File tree

2 files changed

+26
-18
lines changed

2 files changed

+26
-18
lines changed

src/interactions/pointer.js

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,13 @@ function pointerK(kx, ky, {x, y, px, py, maxRadius = 40, channels, ...options} =
5454
if (!facetState) facetStates.set(mark, (facetState = new Map()));
5555
}
5656

57-
const [px, py] = pointerPosition(this, values, dimensions);
57+
// The order of precedence for the pointer position is: px & py; the
58+
// middle of x1 & y1 and x2 & y2; or x1 & y1 (e.g., area); or lastly x &
59+
// y. If a dimension is unspecified, the frame anchor is used.
60+
const [cx, cy] = applyFrameAnchor(this, dimensions);
61+
const {px: PX, py: PY} = values;
62+
const px = PX ? (i) => PX[i] : anchorX(values, cx);
63+
const py = PY ? (i) => PY[i] : anchorY(values, cy);
5864

5965
let i; // currently focused index
6066
let g; // currently rendered mark
@@ -168,14 +174,10 @@ export function pointerY(options) {
168174
return pointerK(0.01, 1, options);
169175
}
170176

171-
// The order of precedence when determining the pointer position is: px & py;
172-
// the middle of x1 & y1 and x2 & y2; or x1 & y1 (e.g., area); or lastly x & y.
173-
// If any dimension is unspecified, we fallback to the frame anchor.
174-
export function pointerPosition(mark, values, dimensions) {
175-
const {px: PX, py: PY, x1: X1, y1: Y1, x2: X2, y2: Y2, x: X = X1, y: Y = Y1} = values;
176-
const [cx, cy] = applyFrameAnchor(mark, dimensions);
177-
return [
178-
PX ? (i) => PX[i] : X1 && X2 ? (i) => (X1[i] + X2[i]) / 2 : X ? (i) => X[i] : () => cx,
179-
PY ? (i) => PY[i] : Y1 && Y2 ? (i) => (Y1[i] + Y2[i]) / 2 : Y ? (i) => Y[i] : () => cy
180-
];
177+
export function anchorX({x1: X1, x2: X2, x: X = X1}, cx) {
178+
return X1 && X2 ? (i) => (X1[i] + X2[i]) / 2 : X ? (i) => X[i] : () => cx;
179+
}
180+
181+
export function anchorY({y1: Y1, y2: Y2, y: Y = Y1}, cy) {
182+
return Y1 && Y2 ? (i) => (Y1[i] + Y2[i]) / 2 : Y ? (i) => Y[i] : () => cy;
181183
}

src/marks/tip.js

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import {getSource} from "../channel.js";
33
import {create} from "../context.js";
44
import {defined} from "../defined.js";
55
import {formatDefault} from "../format.js";
6-
import {pointerPosition} from "../interactions/pointer.js";
6+
import {anchorX, anchorY} from "../interactions/pointer.js";
77
import {Mark} from "../mark.js";
88
import {maybeAnchor, maybeFrameAnchor, maybeTuple, number, string} from "../options.js";
9-
import {applyDirectStyles, applyIndirectStyles, applyTransform, impliedString} from "../style.js";
9+
import {applyDirectStyles, applyFrameAnchor, applyIndirectStyles, applyTransform, impliedString} from "../style.js";
1010
import {inferTickFormat} from "./axis.js";
1111
import {applyIndirectTextStyles, defaultWidth, ellipsis, monospaceWidth} from "./text.js";
1212
import {cut, clipper, splitter, maybeTextOverflow} from "./text.js";
@@ -78,25 +78,31 @@ export class Tip extends Mark {
7878
this.splitLines = splitter(this);
7979
this.clipLine = clipper(this);
8080
}
81-
render(index, scales, channels, dimensions, context) {
81+
render(index, scales, values, dimensions, context) {
8282
const mark = this;
8383
const {x, y, fx, fy} = scales;
8484
const {ownerSVGElement: svg, document} = context;
8585
const {anchor, monospace, lineHeight, lineWidth} = this;
8686
const {textPadding: r, pointerSize: m, pathFilter} = this;
8787
const {marginTop, marginLeft} = dimensions;
88-
const sources = getSources(channels);
88+
const sources = getSources(values);
8989

9090
// The anchor position is the middle of x1 & y1 and x2 & y2, if available,
9191
// or x & y; the former is considered more specific because it’s how we
9292
// disable the implicit stack and interval transforms. If any dimension is
9393
// unspecified, we fallback to the frame anchor. We also need to know the
9494
// facet offsets to detect when the tip would draw outside the plot, and
9595
// thus we need to change the orientation.
96-
const {x1: X1, y1: Y1, x2: X2, y2: Y2, x: X = X1 ?? X2, y: Y = Y1 ?? Y2} = channels;
96+
const {x1: X1, y1: Y1, x2: X2, y2: Y2, x: X = X1 ?? X2, y: Y = Y1 ?? Y2} = values;
9797
const ox = fx ? fx(index.fx) - marginLeft : 0;
9898
const oy = fy ? fy(index.fy) - marginTop : 0;
99-
const [px, py] = pointerPosition(mark, channels, dimensions);
99+
100+
// The order of precedence for the anchor position is: the middle of x1 & y1
101+
// and x2 & y2; or x1 & y1 (e.g., area); or lastly x & y. If a dimension is
102+
// unspecified, the frame anchor is used.
103+
const [cx, cy] = applyFrameAnchor(this, dimensions);
104+
const px = anchorX(values, cx);
105+
const py = anchorY(values, cy);
100106

101107
// Resolve the text metric implementation. We may need an ellipsis for text
102108
// truncation, so we optimistically compute the ellipsis width.
@@ -123,7 +129,7 @@ export class Tip extends Mark {
123129
const channel = sources[key];
124130
const value = channel.value[i];
125131
if (!defined(value) && channel.scale == null) continue;
126-
const color = channel.scale === "color" ? channels[key][i] : undefined;
132+
const color = channel.scale === "color" ? values[key][i] : undefined;
127133
if (key === "x2" && "x1" in sources) {
128134
yield [formatLabel(scales, channel, "x"), formatPair(sources.x1, channel, i)];
129135
} else if (key === "y2" && "y1" in sources) {

0 commit comments

Comments
 (0)