Skip to content
Open

fit tip #2388

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
12 changes: 11 additions & 1 deletion src/marks/tip.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,19 @@ export class Tip extends Mark {
: fitTop && fitBottom
? fitLeft
? "left"
: "right"
: fitRight
? "right"
: "bottom"
: (fitLeft || fitRight) && (fitTop || fitBottom)
? `${fitBottom ? "bottom" : "top"}-${fitLeft ? "left" : "right"}`
: fitLeft
? "left"
: fitRight
? "right"
: fitTop
? "top"
: fitBottom
? "bottom"
: mark.preferredAnchor;
}
const path = this.firstChild; // note: assumes exactly two children!
Expand Down
29 changes: 29 additions & 0 deletions test/output/tipAnchorOverflow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 29 additions & 0 deletions test/output/tipAnchorOverflowY.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
65 changes: 65 additions & 0 deletions test/output/tipAnchorPositions.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions test/plots/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ import "./text-overflow.js";
import "./this-is-just-to-say.js";
import "./tick-format.js";
import "./time-axis.js";
import "./tip-anchor.js";
import "./tip-format.js";
import "./tip.js";
import "./title.js";
Expand Down
75 changes: 75 additions & 0 deletions test/plots/tip-anchor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import * as Plot from "@observablehq/plot";
import {test} from "test/plot";

// Test tip anchor selection near the right edge of the chart.
test(async function tipAnchorOverflow() {
const plot = Plot.rectX([1, 1, 1, 1, 1], {
x: Plot.identity,
fill: Plot.indexOf,
title: () =>
"Lorem ipsum lorem ipsum lorem ipsum Lorem ipsum lorem ipsum lorem ipsum Lorem ipsum lorem ipsum lorem ipsum",
tip: true
}).plot({height: 80, marginTop: 20, axis: null});
plot.dispatchEvent(
new PointerEvent("pointermove", {
pointerType: "mouse",
clientX: 580,
clientY: 30
})
);
return Object.assign(plot, {ready: new Promise((resolve) => setTimeout(resolve, 100))});
});

// Test tip anchor selection near the bottom edge of the chart.
test(async function tipAnchorOverflowY() {
const plot = Plot.rectY([1, 1, 1, 1, 1], {
y: Plot.identity,
fill: Plot.indexOf,
title: () =>
"Lorem ipsum lorem ipsum lorem ipsum Lorem ipsum lorem ipsum lorem ipsum Lorem ipsum lorem ipsum lorem ipsum",
tip: {lineWidth: 5}
}).plot({width: 80, marginLeft: 20, axis: null});
plot.dispatchEvent(
new PointerEvent("pointermove", {
pointerType: "mouse",
clientX: 30,
clientY: 20
})
);
return Object.assign(plot, {ready: new Promise((resolve) => setTimeout(resolve, 100))});
});

// Test tip anchor selection at all 9 positions across the chart.
test(async function tipAnchorPositions() {
const data = [];
for (const px of [40, 320, 600]) {
for (const py of [20, 100, 180]) {
data.push({px, py});
}
}
const plot = Plot.plot({
width: 640,
height: 200,
axis: null,
inset: 20,
marks: [
Plot.dot(data, {x: "px", y: "py", r: 5, fill: "currentColor"}),
Plot.tip(data, {
x: "px",
y: "py",
title: () => "A tip that is wide enough to test anchor fitting behavior across positions"
})
]
});
// Dispatch a pointer event to trigger all tips
for (const {px, py} of data) {
plot.dispatchEvent(
new PointerEvent("pointermove", {
pointerType: "mouse",
clientX: px,
clientY: py
})
);
}
return Object.assign(plot, {ready: new Promise((resolve) => setTimeout(resolve, 100))});
});