Is it possible to draw text on a canvas that has an ellipsis at the end of the text if the text won't fit in the available width and needs to be truncated? Thanks.
Inline overflow occurs when the text in a line overflows the available width without a breaking opportunity. To force overflow to occur and ellipses to be applied, the author must apply the nowrap value to the white-space property on the element, or wrap the content in a <NOBR> tag.
To fix this problem, avoid using vw for your max-width and use a max-width of 100% instead. This will transfer the width of the parent container to the width of the child container.
So, if you've arrived at this question because you're having difficulties getting the ellipsis to operate inside a display: Try adding min-width: 0 to the outmost container that's overflowing its parent, even if you've previously set overflow: hidden to it, and see how it works for you.
text-overflow: ellipsis only works when the following is true: Parent element is not set to display: inline (span's default,) You must use display: block or display: inline-block. The element's width must be constrained in px (pixels) – it doesn't work with values specified using % (percent.)
Top voted answer causes performance issue when working with large number of text.
Here's adapted version using binary search to speed up the search for right length of string.
const binarySearch = ({ max, getValue, match }) => {
let min = 0;
while (min <= max) {
let guess = Math.floor((min + max) / 2);
const compareVal = getValue(guess);
if (compareVal === match) return guess;
if (compareVal < match) min = guess + 1;
else max = guess - 1;
}
return max;
};
const fitString = (
ctx,
str,
maxWidth,
) => {
let width = ctx.measureText(str).width;
const ellipsis = '…';
const ellipsisWidth = ctx.measureText(ellipsis).width;
if (width <= maxWidth || width <= ellipsisWidth) {
return str;
}
const index = binarySearch({
max: str.length,
getValue: guess => ctx.measureText(str.substring(0, guess)).width,
match: maxWidth - ellipsisWidth,
});
return str.substring(0, index) + ellipsis;
};
There is no standard function.
As I needed one, I made this small function that computes the best fitting string :
function fittingString(c, str, maxWidth) {
var width = c.measureText(str).width;
var ellipsis = '…';
var ellipsisWidth = c.measureText(ellipsis).width;
if (width<=maxWidth || width<=ellipsisWidth) {
return str;
} else {
var len = str.length;
while (width>=maxWidth-ellipsisWidth && len-->0) {
str = str.substring(0, len);
width = c.measureText(str).width;
}
return str+ellipsis;
}
}
where c
is the 2D context.
You can draw the string normally after having set your font and other drawing parameters of your canvas :
c.fillText(fittingString(c, "A big string that will likely be truncated", 100), 50, 50);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With