Element
Elements represent graphical objects in a page or group
Element represents a graphical object on the page or inside a group. An element can have one of these types:
- text
- image
- svg
- line
- figure
- video
- group
const element = store.activePage.addElement({
type: 'text',
x: 50,
y: 50,
fill: 'black',
text: 'hello',
});
// logs 50
console.log(element.x);
// set new position
element.set({ x: 100 });
Basic actions
Read properties
At any time, you can access any property of an element. See documentation for every element type to view all available properties.
const element = store.selectedElements[0];
// logs type of element
console.log(element.type);
// logs id of element
console.log(element.id);
element.set(attrs)
Set new attributes to the element.
text.set({ x: text.x + 10, text: 'new text' });
Custom properties
You can't write any arbitrary property directly on an element. If you want to store additional data, use the custom
attribute.
// 🛑 this line will not work, because elements have no attribute `userId`
element.set({ userId: '12' });
// 🟢 you can write such data into "custom" attribute
element.set({ custom: { userId: '12' } });
// read custom attribute
console.log(element.custom?.userId);
element.moveUp()
Move element up on z-index.
text.moveUp();
element.moveDown()
Move element down on z-index.
text.moveDown();
element.moveTop()
Move element to the top of the page or a group.
text.moveTop();
element.moveBottom()
Move element to the bottom of the page or a group.
text.moveBottom();
Locking
Use draggable
, contentEditable
, styleEditable
, removable
and resizable
attributes to lock element editing.
// lock the object
element.set({
// can element be moved and rotated
draggable: false,
// can we change content of element?
contentEditable: false,
// can we change style of element?
styleEditable: false,
// can we resize element?
resizable: false,
// can we remove an element?
removable: false,
});
console.log(element.locked); // true
// unlock it
element.set({
// can element be moved and rotated
draggable: true,
// can we change content of element?
contentEditable: true,
// can we change style of element?
styleEditable: true,
// can we resize element?
resizable: true,
removable: true,
});
Text element
Text elements allow you to create text on the canvas.
Here is the example of default properties:
page.addElement({
type: 'text',
x: 0,
y: 0,
rotation: 0,
locked: false, // deprecated
blurEnabled: false,
blurRadius: 10,
brightnessEnabled: false,
brightness: 0,
shadowEnabled: false,
shadowBlur: 5,
shadowOffsetX: 0,
shadowOffsetY: 0,
shadowColor: 'black',
shadowOpacity: 1,
name: '', // name of element, can be used to find element in the store
text: 'Hey, polotno',
// placeholder is working similar to input placeholder
// it will be rendered if no text is defined
// and we will use it in input element too
// useful for template canvas, where users will need to replace text elements
// important (!) placeholders are removed from export result
placeholder: '',
fontSize: 14,
fontFamily: 'Roboto',
fontStyle: 'normal', // can be normal or italic
fontWeight: 'normal', // can be normal or bold or some other CSS variations
textDecoration: '',
fill: 'black',
align: 'center',
width: 0,
strokeWidth: 0,
stroke: 'black',
lineHeight: 1,
letterSpacing: 0, // % from font size,
backgroundEnabled: false,
backgroundColor: '#7ED321',
backgroundOpacity: 1,
backgroundCornerRadius: 0.5, // % from half line height
backgroundPadding: 0.5, //% from half line height
// can user select element?
// if false, element will be "invisible" for user clicks
selectable: true,
// use for absolute positing of element
alwaysOnTop: false,
// also we can hide some elements from the export
showInExport: true,
// can element be moved and rotated
draggable: true,
// can we change content of element?
contentEditable: true,
// can we remove element from UI with button or keyboard?
removable: true,
// can we resize element?
resizable: true,
// can we change style of element?
styleEditable: true,
});
text.toggleEditMode()
Enable edit mode for the text. It puts the cursor inside the text and a user can do regular text editing. You can call text.toggleEditMode()
programmatically (e.g. right after creating a new text element).
Image element
Image element draws an image on the canvas. By default images do smart-cropping to fit into its size.
page.addElement({
type: 'image',
x: 0,
y: 0,
rotation: 0,
locked: false, // deprecated
blurEnabled: false,
blurRadius: 10,
brightnessEnabled: false,
brightness: 0,
shadowEnabled: false,
shadowBlur: 5,
shadowOffsetX: 0,
shadowOffsetY: 0,
shadowColor: 'black',
shadowOpacity: 1,
name: '', // name of element, can be used to find element in the store
// url path to image
src: 'https://example.com/image.png',
keepRatio: false, // can we change aspect ratio of element on resize
stretchEnabled: false, // can we stretch image on any axis
// url path to svg or image that will be used to clip image
// can be used for image framing
clipSrc: '',
width: 100,
height: 100,
cropX: 0, // 0-1 : % from original image width
cropY: 0, // 0-1 : % from original image height
cropWidth: 1, // 0-1 : % from original image width
cropHeight: 1, // 0-1 : % from original image height
cornerRadius: 0,
borderColor: 'black',
borderSize: 0,
flipX: false,
flipY: false,
// can user select element?
// if false, element will be "invisible" for user clicks
selectable: true,
// use for absolute positing of element
alwaysOnTop: false,
// also we can hide some elements from the export
showInExport: true,
// can element be moved and rotated
draggable: true,
// can we change content of element?
contentEditable: true,
// can we remove element from UI with button or keyboard?
removable: true,
// can we resize element?
resizable: true,
});
image.toggleCropMode()
Enter into "crop mode" of the image programmatically.
<Button
minimal
icon={<Crop />}
// use capture handler to handle click event sooner
onClickCapture={(e) => {
// stop propagation to prevent autohide of crop mode on current click
e.stopPropagation();
element.toggleCropMode(true);
}}
/>
Image filters
Polotno recognizes two filter categories, each with its own API pattern.
- Old filters (use
element.set
):
sepiaEnabled
grayscaleEnabled
blurEnabled, blurRadius
brightnessEnabled, brightness
- Combined filters (use
element.setFilter
):
cold
natural
warm
temperature
contrast
highlights
shadows
white
black
saturation
vibrance
Examples:
// 1. Old filters
shape.set({ sepiaEnabled: true });
shape.set({ blurEnabled: true, blurRadius: 12 });
shape.set({ brightnessEnabled: true, brightness: 0.25 }); // +25 %
// 2. One‑active preset (replaces previous preset)
shape.setFilter('warm');
// 3. Combined numeric filters (stackable)
shape.setFilter('temperature', -0.2);
shape.setFilter('contrast', 0.15);
shape.setFilter('vibrance', 0.3);
// disabling:
// Old filters off
shape.set({
sepiaEnabled: false,
blurEnabled: false,
brightnessEnabled: false,
});
// Remove current preset
shape.setFilter('warm', null);
// Clear all combined filters
['temperature', 'contrast', 'highlights', 'shadows', 'white', 'black', 'saturation', 'vibrance']
.forEach((f) => shape.setFilter(f, null));
SVG element
SVG elements work similarly to Image elements but can replace internal colors.
const svgElement = page.addElement({
type: 'svg',
src: 'https://example.com/image.svg',
maskSrc: '', // should we draw mask image over svg element?
keepRatio: false, // can we change aspect ratio of svg?
stretchEnabled: false, // can we stretch image on any axis
x: 0,
y: 0,
rotation: 0,
locked: false, // deprecated
blurEnabled: false,
blurRadius: 10,
brightnessEnabled: false,
brightness: 0,
shadowEnabled: false,
shadowBlur: 5,
shadowOffsetX: 0,
shadowOffsetY: 0,
shadowColor: 'black',
shadowOpacity: 1,
name: '', // name of element, can be used to find element in the store
width: 100,
height: 100,
flipX: false,
flipY: false,
cornerRadius: 0,
// can user select element?
// if false, element will be "invisible" for user clicks
selectable: true,
// use for absolute positing of element
alwaysOnTop: false,
// also we can hide some elements from the export
showInExport: true,
// can element be moved and rotated
draggable: true,
// can we change content of element?
contentEditable: true,
// can we remove element from UI with button or keyboard?
removable: true,
// can we resize element?
resizable: true,
// map of originalColor -> newColor, used to replace colors in svg image
// do not change it manually. Instead use `el.replaceColor(originalColor, newColor)`
colorsReplace: {},
});
If you want to detect colors in an SVG string you can use this:
import { urlToString, getColors, useSvgColors } from 'polotno/utils/svg';
// in react component:
const Toolbar = ({ element }) => {
const colors = useSvgColors(element.src); // will return array of colors detected in the svg image
};
// in functions:
async function getSvgColors(element) {
const svgString = await urlToString(element.src);
const colors = getColors(svgString);
}
svgElement.replaceColor(oldColor, newColor)
Some SVG files support color replacement when a color is defined as fill
on internal nodes. You can replace specific colors to modify the original image.
svgElement.replaceColor('red', 'blue');
Line element
Use line elements to draw lines and arrows on the canvas. For now, line elements may not support all available filters from JSON.
const lineElement = page.addElement({
type: 'line',
x: 0,
y: 0,
width: 400,
height: 10,
name: '', // name of element, can be used to find element in the store
color: 'black',
rotation: 0,
dash: [], // array of numbers, like [5, 5]
startHead: '', // can be empty, arrow, triangle, circle, square, bar
endHead: '', // can be empty, arrow, triangle, circle, square, bar
// can user select element?
// if false, element will be "invisible" for user clicks
selectable: true,
// use for absolute positing of element
alwaysOnTop: false,
// also we can hide some elements from the export
showInExport: true,
// can element be moved and rotated
draggable: true,
// can we change content of element?
contentEditable: true,
// can we remove element from UI with button or keyboard?
removable: true,
// can we resize element?
resizable: true,
styleEditable: true,
});
Figure element
Use figure to draw basic shapes on the canvas. It has a large collection of shapes controlled by subType
.
const figureElement = page.addElement({
type: 'figure',
subType: 'rect',
x: 0,
y: 0,
width: 400,
height: 400,
fill: 'black',
stroke: 'red',
strokeWidth: 40,
cornerRadius: 40,
});
Currently supported list of subType
:
rect, circle, star, triangle, rightTriangle, diamond, pentagon, hexagon, speechBubble, cross, arc, cloud, rightArrow, leftArrow, downArrow, upArrow, asterisk1, asterisk2, bookmark, butterfly, cylinder, diamond2, door, drop1, drop2, explosion, flag, flower, frame, heart1, home, home2, hourglass, house, keyhole, kiss, leaf, lightning1, lightning2, magnet, mithosis, orangeRicky, party, pillow, polygon, rainbow, rhodeIsland, shell, shield1, shield2, skewedRectangle, softFlower, softStar, stairs1, stairs2, teewee, blob1, blob10, blob11, blob12, blob13, blob14, blob15, blob16, blob17, blob18, blob19, blob2, blob20, blob21, blob22, blob23, blob24, blob25, blob26, blob27, blob28, blob29, blob3, blob30, blob31, blob32, blob4, blob5, blob6, blob7, blob8, blob9
Video element
Use video to render a video on the canvas. Video element has many properties similar to the image element.
const videoElement = page.addElement({
type: 'video',
x: 0,
y: 0,
rotation: 0,
// url path to video
src: 'https://example.com/image.png',
// start/end time of video in % from video duration
// can be used for trimming video
startTime: 0,
endTime: 1,
shadowEnabled: false,
shadowBlur: 5,
shadowOffsetX: 0,
shadowOffsetY: 0,
shadowColor: 'black',
shadowOpacity: 1,
name: '', // name of element, can be used to find element in the store
width: 100,
height: 100,
cropX: 0, // 0-1 : % from original image width
cropY: 0, // 0-1 : % from original image height
cropWidth: 1, // 0-1 : % from original image width
cropHeight: 1, // 0-1 : % from original image height
borderColor: 'black',
borderSize: 0,
flipX: false,
flipY: false,
// can user select element?
// if false, element will be "invisible" for user clicks
selectable: true,
// use for absolute positing of element
alwaysOnTop: false,
// also we can hide some elements from the export
showInExport: true,
// can element be moved and rotated
draggable: true,
// can we change content of element?
contentEditable: true,
// can we remove element from UI with button or keyboard?
removable: true,
// can we resize element?
resizable: true,
});
Group element
Group element is a container for other elements. It can be used to move multiple elements together.
Here is the example of default properties and usage:
const page = store.addPage();
page.addElement({
type: 'text',
text: 'Hello world',
id: 'text-1',
});
page.addElement({
type: 'text',
text: 'Hello world',
id: 'text-2',
});
const group = store.groupElements(['text-1', 'text-2']);
group.set({
name: 'group',
opacity: 0.5,
custom: {},
visible: true,
selectable: true,
removable: true,
alwaysOnTop: false,
showInExport: true,
});
// ungroup:
store.ungroupElements([group.id]);