Out of the box, Polotno
does not support the rendering of rich text elements, meaning you cannot apply different styles, colors, fonts, etc., to parts of the text. The entire text
element must maintain a uniform style. However, Polotno offers support for rich text elements, which must be explicitly activated.
How to enable rich text support?
import { unstable_useHtmlTextRender } from 'polotno/config';
unstable_useHtmlTextRender(true);
store.activePage.addElement({
type: 'text',
text: 'Hello <strong>from rich</strong> <u>text</u> <span style="color: red;">support</span>!',
y: 300,
x: store.width / 2 - 200,
fontSize: 80,
width: 400,
});
When 'html renderer' is enabled, Polotno
will use very different rendering logic for text elements. Rich text may drop the performance of your application if you have many text elements. Please report any issues you may come across.
Polotno has many clients who use these settings on production. The feature considered as stable and supported. The "unstable" prefix will be removed soon.
If you use Cloud Render API, please make sure to pass htmlTextRenderEnabled: true
to enable rich mode.
Controlling rich text from external UI
Internally, rich text is represented as HTML string. You can modify it with any tools to apply the changes. There are some built-in methods that you can use to change formats.
Internally, Polotno is using https://quilljs.com/ library to manipulate text. When text element is in "edit mode" (when user double-click on it) you can use these methods:
import { quillRef } from 'polotno/canvas/html-element';
console.log(quillRef.currentFormat);
console.log(quillRef.editor.intance);
<Button
onMouseDown={(e) => {
e.preventDefault();
}}
onClick={() => {
const quill = quillRef.editor.intance;
const selection = quill.getSelection();
quill.formatText(
selection.index,
selection.length,
'bold',
!quillRef.currentFormat.bold,
'user'
);
}}
/>
In numerous instances, you may want to change format, while a text
element is not in edit mode. In that case you can create a Quill instance temporary in memory -> apply changes -> save resulted HTML into the element.
import { createQuill, setQuillContent } from 'polotno/canvas/html-element';
const createTempQuill = ({ html }) => {
const el = document.createElement('div');
document.body.appendChild(el);
el.style.display = 'none';
el.style.whiteSpace = 'pre-wrap';
const quill = createQuill(el);
setQuillContent(quill, html);
return quill;
};
const removeTempQuill = (quill) => {
quill.root.parentElement.remove();
};
const quill = createTempQuill({ html: element.text });
quill.setSelection(0, quill.getLength(), 'api');
quill.format('bold', false);
const innerHtml = quill.root.innerHTML;
removeTempQuill(quill);
element.set({ text: innerHtml });
Here is a full real-world example of "bold" format button:
const ToggleButton = observer(
({
active,
globalActive,
format,
element,
disableGlobal,
enableGlobal,
icon,
}: {
active: boolean;
globalActive: boolean;
format: string;
element: TextElementType;
disableGlobal: () => void;
enableGlobal: () => void;
icon: any;
}) => {
return (
<Button
minimal
icon={icon}
active={active}
onMouseDown={(e) => {
e.preventDefault();
}}
onClick={(e) => {
let quill = window.__polotnoQuill;
if (quill) {
const selection = quill.getSelection();
quill.formatText(
selection.index,
selection.length,
format,
!quillRef.currentFormat[format],
'user'
);
if (globalActive) {
disableGlobal();
}
return;
}
quill = createTempQuill({ html: element.text });
quill.setSelection(0, quill.getLength(), 'api');
quill.format(format, false);
const innerHtml = quill.root.innerHTML;
removeTempQuill(quill);
element.set({ text: innerHtml });
if (globalActive) {
disableGlobal();
} else {
enableGlobal();
}
}}
/>
);
}
);
export const TextBold = observer(({ element, store }) => {
return (
<ToggleButton
format="bold"
active={
quillRef.currentFormat.bold ||
element.fontWeight === 'bold' ||
element.fontWeight === '700'
}
globalActive={
element.fontWeight === 'bold' || element.fontWeight === '700'
}
element={element}
disableGlobal={() => element.set({ fontWeight: 'normal' })}
enableGlobal={() => element.set({ fontWeight: 'bold' })}
icon={<Bold />}
/>
);
});
Define quill editor formats
You can hook into the quill editor to change the list of available formats or define your own:
import { unstable_setQuillFormats } from 'polotno/config';
unstable_setQuillFormats([
'bold',
'color',
'font',
'italic',
'size',
'strike',
'underline',
'indent',
'list',
'direction',
'font-weight'
]);
import Quill from "quill";
const Inline = Quill.import("blots/inline");
class FontWeightBlot extends Inline {
static create(value) {
const node = super.create();
node.style.fontWeight = value;
return node;
}
static formats(node) {
return node.style.fontWeight;
}
}
FontWeightBlot.blotName = "font-weight";
FontWeightBlot.tagName = "span";
Quill.register(FontWeightBlot);