Reputation: 343
In Konva, we can use attributes like fontSize
to determine the text size.
But we want more, we are implementing a feature that can allow us to shrink the text size automatically.
For example, we have a text element in canvas with different lengths of paragraphs.
we want to dynamically determine fontsize
to fit in the text DOM.
So, if the width and height don't have enough space to accommodate text, then we adjust fontsize smaller.
if the width and height can accommodate text, then we make fontsize bigger.
We found this post, but the downside is that will keep text in one line. if your paragraph has multiple lines, then the font will be very small and only one line.
Is there any workaround or idea we can try? I think the issue is we need to calculate the text is over boundary or not.
Upvotes: 1
Views: 1115
Reputation: 191
For my it worked the solution on this Konva Issue thread but I added some modifications so the shrinking could work while editing the text as well
I use this to get the amount of lines needed to fit the text in the box and then multiplied to the line height:
textNode.textArr.length * textNode.textHeight
See a working demo and the code here: https://codepen.io/leonfhl/pen/qBLaeBg
Upvotes: 0
Reputation: 343
I found a workaround, now I can implement auto-shrinking for my text element.
/**
* Returns an array of all non-whitespace character "tokens" / "chunks" / words
* @param {string} text The source text
* @returns {string[]} Non whitespace tokens in string
*/
function getTokensInString(text) {
if (typeof text === "string") {
var result = [];
var tokens = text.split(" ");
for(var i = 0; i < tokens.length; i++) {
if (tokens[i].length > 0) {
result.push(tokens[i]);
}
}
return result;
}
return [];
}
/**
* Detect whether Konva.Text rendered any words that were broken across lines
*
* @param {string[]} sourceTokens An array of string tokens from original text passed to Konva.Text()
* @param {Object[]} renderLines The contents of Konva.Text.textArr
*/
function hasBrokenWords (sourceTokens, renderLines) {
var combined = "";
for (var i = 0; i < renderLines.length; i++) {
combined += (i === 0 ? "" : " ") + renderLines[i].text;
}
var a = sourceTokens;
var b = getTokensInString(combined);
if (a.length !== b.length) {
return true;
}
for (var i = 0; i < a.length; i++) {
if (a[i] !== b[i]) {
return true;
}
}
return false;
}
var boxWidth = 600;
var boxHeight = 400;
var textString = "Sentence with a REALLYLONGWORD";
var text = Konva.Text({
text: textString,
width: 600,
fontSize: 120
});
var sourceTokens = getTokensInString(textString);
var brokenWords = hasBrokenWords(sourceTokens, text.textArr);
while(text.getHeight() > boxHeight || brokenWords){
text.fontSize( text.fontSize()- 1);
brokenWords = hasBrokenWords(sourceTokens, text.textArr);
}
The answer comes from Konva issues
Upvotes: 1