Skip to content

Commit a8b6a7c

Browse files
committed
checkpoint svg
1 parent b548977 commit a8b6a7c

File tree

1 file changed

+34
-11
lines changed

1 file changed

+34
-11
lines changed

src/marks/tooltip.js

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ export class Tooltip extends Mark {
3838
let indexes = this.indexesBySvg.get(svg);
3939
if (indexes) return void indexes.push(index);
4040
this.indexesBySvg.set(svg, (indexes = [index]));
41+
const r = 8; // padding
42+
const dx = 0; // offsetLeft
43+
const dy = 12; // offsetTop
4144
const dot = select(svg)
4245
.on("pointermove", (event) => {
4346
let i, xi, yi, fxi, fyi;
@@ -63,26 +66,46 @@ export class Tooltip extends Mark {
6366
dot.attr("display", "none");
6467
} else {
6568
dot.attr("display", "inline");
66-
dot.attr("transform", `translate(${xi},${yi})`);
69+
dot.attr("transform", `translate(${Math.round(xi)},${Math.round(yi)})`);
6770
const text = [];
6871
for (const key in channels) {
6972
const channel = channels[key];
7073
const label = scales[channel.scale]?.label ?? key;
71-
text.push(`${label} = ${formatDefault(channel.value[i])}`);
74+
text.push([label, formatDefault(channel.value[i])]);
7275
}
73-
if (fxv != null) text.push(`${fx.label ?? "fx"} = ${formatFx(fxi)}`);
74-
if (fyv != null) text.push(`${fy.label ?? "fy"} = ${formatFy(fyi)}`);
75-
title.text(text.join("\n"));
76+
if (fxv != null) text.push([fx.label ?? "fx", formatFx(fxi)]);
77+
if (fyv != null) text.push([fy.label ?? "fy", formatFy(fyi)]);
78+
content
79+
.selectChildren()
80+
.data(text)
81+
.join("tspan")
82+
.attr("x", 0)
83+
.attr("y", (d, i) => `${i + 0.9}em`)
84+
.selectChildren()
85+
.data((d) => d)
86+
.join("tspan")
87+
.attr("font-weight", (d, i) => (i ? "bold" : null))
88+
.text((d, i) => (i ? ` ${d}` : String(d)));
89+
// TODO Limit the maximum width and clip.
90+
const {width, height} = content.node().getBBox();
91+
const w = width + r * 2;
92+
const h = height + r * 2;
93+
path.attr("d", `M${dx},${dy}v${-dy}l${dy},${dy}h${w - dy}v${h}h${-w}z`);
7694
}
7795
})
7896
.on("pointerdown pointerleave", () => dot.attr("display", "none"))
7997
.append("g")
80-
.attr("display", "none")
81-
.attr("pointer-events", "all")
82-
.attr("fill", "none")
83-
.call((g) => g.append("circle").attr("r", maxRadius).attr("fill", "none"))
84-
.call((g) => g.append("circle").attr("r", 4.5).attr("stroke", "red").attr("stroke-width", 1.5));
85-
const title = dot.append("title");
98+
.attr("display", "none");
99+
const path = dot
100+
.append("path")
101+
.attr("fill", "white")
102+
.attr("stroke", "black")
103+
.on("pointerdown pointermove", (event) => event.stopPropagation());
104+
const content = dot
105+
.append("text")
106+
.attr("transform", `translate(${dx + r},${dy + r})`)
107+
.attr("text-anchor", "start")
108+
.on("pointerdown pointermove", (event) => event.stopPropagation());
86109
return null;
87110
}
88111
}

0 commit comments

Comments
 (0)