Integrations

Upgrade Konva.Text

Try it in the demo →

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: padding is not carried over, so text that had padding sits that much closer to the box's top-left corner. Konva.Text's verticalAlign, wrap and ellipsis have no rich text equivalent and change nothing.

In the API reference