diff --git a/src/marks/tip.js b/src/marks/tip.js index bfb9d04cb2..fc78bb564e 100644 --- a/src/marks/tip.js +++ b/src/marks/tip.js @@ -45,7 +45,7 @@ export class Tip extends Mark { frameAnchor, format, textAnchor = "start", - textOverflow, + textOverflow = "ellipsis", textPadding = 8, title, pointerSize = 12, @@ -90,7 +90,7 @@ export class Tip extends Mark { const mark = this; const {x, y, fx, fy} = scales; const {ownerSVGElement: svg, document} = context; - const {anchor, monospace, lineHeight, lineWidth} = this; + const {anchor, monospace, lineHeight, lineWidth, textOverflow} = this; const {textPadding: r, pointerSize: m, pathFilter} = this; const {marginTop, marginLeft} = dimensions; @@ -185,13 +185,11 @@ export class Tip extends Mark { title = value.trim(); value = ""; } else { - if (label || (!value && !swatch)) value = " " + value; - const [k] = cut(value, w - widthof(label), widthof, ee); - if (k >= 0) { - // value is truncated - title = value.trim(); - value = value.slice(0, k).trimEnd() + ellipsis; - } + const space = label || (!value && !swatch) ? " " : ""; + const text = clipper({monospace, lineWidth: lineWidth - widthof(label + space) / 100, textOverflow})(value); + // value is truncated + if (text !== value) title = value.trim(); + value = space + text; } const line = selection.append("tspan").attr("x", 0).attr("dy", `${lineHeight}em`).text("\u200b"); // zwsp for double-click if (label) line.append("tspan").attr("font-weight", "bold").text(label); diff --git a/test/output/tipLongTextEllipsisEnd.svg b/test/output/tipLongTextEllipsisEnd.svg new file mode 100644 index 0000000000..e3b5788b45 --- /dev/null +++ b/test/output/tipLongTextEllipsisEnd.svg @@ -0,0 +1,31 @@ + + + + + Long sentence that gets clipped at the end after a certain length + + + x + + + + + x Long sentence that gets clipped at th…Long sentence that gets clipped at the end after a certain length + + + \ No newline at end of file diff --git a/test/output/tipLongTextEllipsisMiddle.svg b/test/output/tipLongTextEllipsisMiddle.svg new file mode 100644 index 0000000000..db970a662a --- /dev/null +++ b/test/output/tipLongTextEllipsisMiddle.svg @@ -0,0 +1,31 @@ + + + + + Long sentence that gets clipped in the middle after a certain length + + + x + + + + + x Long sentence tha…ter a certain lengthLong sentence that gets clipped in the middle after a certain length + + + \ No newline at end of file diff --git a/test/output/tipLongTextEllipsisStart.svg b/test/output/tipLongTextEllipsisStart.svg new file mode 100644 index 0000000000..e8734c2303 --- /dev/null +++ b/test/output/tipLongTextEllipsisStart.svg @@ -0,0 +1,31 @@ + + + + + Long sentence that gets clipped at the start after a certain length + + + x + + + + + x …ped at the start after a certain lengthLong sentence that gets clipped at the start after a certain length + + + \ No newline at end of file diff --git a/test/plots/tip.ts b/test/plots/tip.ts index 6c827e7b85..ade88e8cd7 100644 --- a/test/plots/tip.ts +++ b/test/plots/tip.ts @@ -185,6 +185,27 @@ export async function tipLongText() { return Plot.tip([{x: "Long sentence that gets cropped after a certain length"}], {x: "x"}).plot(); } +export async function tipLongTextEllipsisEnd() { + return Plot.tip([{x: "Long sentence that gets clipped at the end after a certain length"}], { + x: "x", + textOverflow: "ellipsis" // "ellipsis-end" + }).plot(); +} + +export async function tipLongTextEllipsisMiddle() { + return Plot.tip([{x: "Long sentence that gets clipped in the middle after a certain length"}], { + x: "x", + textOverflow: "ellipsis-middle" + }).plot(); +} + +export async function tipLongTextEllipsisStart() { + return Plot.tip([{x: "Long sentence that gets clipped at the start after a certain length"}], { + x: "x", + textOverflow: "ellipsis-start" + }).plot(); +} + export async function tipNewLines() { return Plot.plot({ height: 40,