If your Konva app already shows text with Konva.Text, you don't have to rebuild your designs.
convertKonvaTextToRichText reads a Konva.Text node and returns a rich text box with the same words, the same look
and the same place. Your own attributes, such as an asset id or a lock flag, come along, so the rest of your app keeps
working with the new node.
Convert a node
import { convertKonvaTextToRichText } from "@mycreativeshop/rich-text/konva";
const rich = await convertKonvaTextToRichText(konvaText); // same words, look and place
layer.add(rich);
konvaText.destroy();
rich.getAttr("assetId"); // your own attributes come along
The function is async: it loads the fonts the text uses before it measures, so the new box is laid out in its real font. It returns a RichText that is not on any layer yet. On a stage where you called enableRichText, the box can be selected and edited as soon as you add it.
Replace a node in its place
Add the new box to the same parent at the same stacking position, then remove the old node. If the old node was selected, select the new one:
async function upgrade(konvaText: Konva.Text): Promise<RichText> {
const rich = await convertKonvaTextToRichText(konvaText);
const parent = konvaText.getParent()!;
const index = konvaText.zIndex();
parent.add(rich);
rich.zIndex(index); // the old node's place in the stacking order
if (selection.nodes().includes(konvaText)) selection.nodes([rich]);
konvaText.destroy();
return rich;
}
// Every Konva.Text on a layer
for (const node of layer.find("Text")) await upgrade(node as Konva.Text);
What it reads
| From the Konva.Text | In the rich text box |
|---|---|
text |
The words. Each line break starts a new paragraph. |
fontFamily, fontSize |
The font family and size. The family loads like any other font: see Fonts. |
fontStyle |
Bold and italic. |
A fontWeight attribute |
The numeric weight, from a number or a CSS keyword such as "bold". When fontStyle says bold, the weight is 700, as Konva draws it. |
textDecoration |
Underline and strikethrough. |
fill |
The color, when it is a color string. Any other fill gives the default color. |
stroke, strokeWidth |
The outline's color and width. |
align |
The alignment. |
lineHeight, letterSpacing |
The line height and letter spacing. |
x, y, width |
The position and width. The box's height comes from its text. |
scaleX, scaleY, rotation |
The same scale and rotation. |
opacity, visible, id, name |
The same values. |
A copyfit attribute |
Shrink to fit, when the attribute is enabled. See Shrink to fit. |
| Every other attribute | Copied as it is: draggable, offset, skew, and your own attributes such as assetId. |
A Konva.Text has one style for all of its text, so every paragraph of the new box starts with that style. From there,
people can format any part of it.
Where the text sits
Konva.Text and rich text place the first line's baseline differently. The conversion moves the box so the text's
first baseline sits where Konva drew it, so the box's y differs slightly from the old node's while the text stays in
place. On a rotated node, the box moves along the rotation.
When text with no line breaks measures up to 10 pixels wider than its box, the conversion reduces its font size just enough for it to fit on one line.
Limit: A line that fits its box with a pixel or two to spare may break at a different word after the conversion. Konva.Text measures text with the browser's canvas, and rich text measures the shapes in the font file, so the two widths can differ slightly. Check designs whose lines fill their boxes, and widen a box by a few pixels where a line breaks early.
Limit:
paddingis not carried over, so text that had padding sits that much closer to the box's top-left corner. Konva.Text'sverticalAlign,wrapandellipsishave no rich text equivalent and change nothing.