How to use shapes in the Markup Editor
Shapes are used in the Annotate, Decorate, and the Sticker plugins, they're also used to render image overlays in the willRenderCanvas
hook of the editor.
The editor also uses shapes internally to draw parts of the user interface.
Working with Shapes
In the examples below we'll interact with the imageAnnotation
property. In the same manner we can update the imageDecoration
property and imageRedaction
property.
We can set the imageAnnotation
property to an array of shapes and the editor will draw the shapes to the screen.
This example will draw a red square in the top left corner of the image.
import { openDefaultEditor } from './pintura.js';
openDefaultEditor({
imageAnnotation: [
{
x: 0,
y: 0,
width: 128,
height: 128,
backgroundColor: [1, 0, 0],
},
],
});
Let's add a green circle to the view.
import { openDefaultEditor } from './pintura.js';
const editor = openDefaultEditor({
imageAnnotation: [
// a red square
{
id: 'square',
x: 0,
y: 0,
width: 128,
height: 128,
backgroundColor: [1, 0, 0],
},
],
});
// when some button is clicked a green circle is added
someButton.addEventListener('click', () => {
// we merge our new circle shape with the existing list of shapes
// it's added at the end of the list, so it will be drawn on top
editor.imageAnnotation = [
...editor.imageAnnotation,
{
id: 'circle',
rx: 128,
ry: 128,
width: 64,
height: 64,
backgroundColor: [0, 1, 0],
},
];
});
Now le'ts change the color of the red square to blue.
import { openDefaultEditor } from './pintura.js';
const editor = openDefaultEditor({
imageAnnotation: [
// a red square
{
id: 'square',
x: 0,
y: 0,
width: 128,
height: 128,
backgroundColor: [1, 0, 0],
},
],
});
// when some button is clicked the red square changes color to blue
someButton.addEventListener('click', () => {
editor.imageAnnotation = editor.imageAnnotation.map((shape) => {
// if it's the square, copy and overwrite background color property
if (shape.id === 'square') {
return {
...shape,
backgroundColor: [0, 0, 1],
};
}
// else return shape
return shape;
});
});
Now let's remove the red square
import { openDefaultEditor } from './pintura.js';
const editor = openDefaultEditor({
imageAnnotation: [
// a red square
{
id: 'square',
x: 0,
y: 0,
width: 128,
height: 128,
backgroundColor: [1, 0, 0],
},
// a green circle
{
id: 'circle',
rx: 128,
ry: 128,
width: 64,
height: 64,
backgroundColor: [0, 1, 0],
},
],
});
// when some button is clicked the red square is removed
someButton.addEventListener('click', () => {
// this removes the red square
editor.imageAnnotation = editor.imageAnnotation.filter(
(shape) => shape.id !== 'square'
);
});
Types
Pintura Image Editor determines the type of a shape (and how to draw and interact with it) based on the defined props on the shape.
Name | Requirements |
---|---|
Path | Has points property.
|
Line | Has x1 , y1 , x2 , and y2 property.
|
Rectangle | Has width , height properties. Or a width and height can be derived from the bounds properties x , y , top , right , bottom , and left .
|
Ellipse | Has rx and ry property.
|
Text | Has text property.
|
Triangle | Has x1 , y1 , x2 , y2 , x3 , and y3 property
|
Styles
Layout related styles can be defined in pixels or in percentages.
When defined in percentages the Pintura Image Editor will calculate the pixel value automatically relative to the shape parent context.
When annotating an image the parent context is the image itself, when decorating a crop, the parent context is the crop selection.
const absoluteShape = {
x: 0,
y: 0,
// ...other styles
};
const relativeShape = {
x: '10%',
y: '15%',
// ...other styles
};
Shared
Property | Description |
---|---|
x |
The x position of the shape. Either in pixels or a percentage.
|
y |
The y position of the shape. Either in pixels or a percentage.
|
rotation |
Shape rotation in radians. |
backgroundColor |
Array of 3 or 4 color values ranging between 0 and 1 .
|
opacity |
The opacity of the shape. Value between 0 and 1
|
alwaysOnTop |
If set to true the shape will be sorted to appear above other shapes.
|
rotation
The rotation of the shape in radians.
const shape = {
rotation: Math.PI / 4, // 45 degrees
// ...other styles
};
If you want to set the rotation in degrees you can use the degToRad
method.
import { degToRad } from './pintura.js';
const shape = {
rotation: degToRad(45),
// ...other styles
};
alwaysOnTop
If set to true
the shape will be sorted to appear above other shapes.
When multiple shapes have this property set to true
the order of the shapes in the shape array is retained.
Shape draw order runs from top to bottom. In the example below the green circle is drawn first, then the blue square and then the red square.
import { openDefaultEditor } from './pintura.js';
const editor = openDefaultEditor({
imageAnnotation: [
// 2. a blue square
{
id: 'square',
x: 32,
y: 32,
width: 128,
height: 128,
backgroundColor: [0, 0, 1],
alwaysOnTop: true,
},
// 3. a red square
{
id: 'square',
x: 0,
y: 0,
width: 128,
height: 128,
backgroundColor: [1, 0, 0],
alwaysOnTop: true,
},
// 1. a green circle
{
id: 'circle',
rx: 128,
ry: 128,
width: 64,
height: 64,
backgroundColor: [0, 1, 0],
},
],
});
Eraser
const shape = {
eraseRadius: 0,
};
Property | Description |
---|---|
eraseRadius |
The radius around the erase position to remove shapes in. Increase to make it easier to remove small shapes. |
Rectangle
const shape = {
x: 0,
y: 0,
width: 128,
height: 128,
backgroundColor: [1, 0, 0],
};
Property | Description |
---|---|
width |
The width of the rectangle.
|
height |
The height of the rectangle.
|
left |
The position of the rectangle relative to the left of its context.
|
top |
The position of the rectangle relative to the top of its context.
|
right |
The position of the rectangle relative to the right of its context.
|
bottom |
The position of the rectangle relative to the bottom of its context.
|
cornerRadius |
The rectangle corner radius. |
backgroundImage |
The resource to use as a background image for this shape. |
backgroundSize |
How the image is fitted in the rectangle, either undefined , 'contain' , or 'cover' .
|
aspectRatio |
The aspect ratio the rectangle should adhere to. |
strokeColor |
Array of 3 or 4 color values ranging between 0 and 1. |
strokeWidth |
The width of the stroke to use for the rectangle. |
backgroundSize
When set to undefined
the shape will be forced to match the backgroundImage
aspect ratio.
Set the value to 'contain'
to center the backgroundImage
in the rectangle.
Setting the value to 'cover'
will cover the rectangle with the backgroundImage
.
Setting the value to 'force'
will skew the backgroundImage
to fit the shape.
Ellipse
const shape = {
x: 32,
y: 32,
rx: 64,
ry: 64,
backgroundColor: [1, 0, 0],
};
Property | Description |
---|---|
rx |
The radius of the ellipse on the x axis. |
ry |
The radius of the ellipse on the y axis. |
strokeColor |
Array of 3 or 4 color values ranging between 0 and 1. |
strokeWidth |
The width of the stroke to use for the ellipse. |
Line
const shape = {
x1: 0,
y1: 0,
x2: 128,
y2: 128,
strokeColor: [1, 0, 0],
};
Property | Description |
---|---|
x1 |
The start position of the line on the x axis. |
y1 |
The start position of the line on the y axis. |
x2 |
The end position of the line on the x axis. |
y2 |
The end position of the line on the y axis. |
strokeColor |
Array of 3 or 4 color values ranging between 0 and 1. |
strokeWidth |
The width of the stroke to use for the line. |
lineStart |
The decorative shape to use for the start of the line. |
lineEnd |
The decorative shape to use for the end of the line. |
If we're not using one of the default editor factory methods we need to set set the shapePreprocessor
property to render lineStart
and lineEnd
styles.
For the possible lineStart
and lineEnd
values see lineStart and lineEnd styles
Text
const shape = {
x: 0,
y: 0,
width: 128,
height: 128,
text: 'Hello World',
fontWeight: 'bold',
color: [1, 0, 0],
};
Property | Description |
---|---|
fontSize |
The font size to use for the text. |
fontFamily |
The font family to use for the text. |
fontWeight |
The font weight to use for the text. |
fontStyle |
The font style to use for the text. |
fontVariant |
The font variant to use for the text. |
lineHeight |
The line height of the text. |
color |
Array of 3 or 4 color values ranging between 0 and 1 .
|
textAlign |
Alignment of the text, "left", "center", or "right", defaults to "left". |
text |
The text to show. |
Path
const shape = {
points: [
{
x: 0,
y: 0,
},
{
x: 128,
y: 0,
},
{
x: 128,
y: 128,
},
{
x: 0,
y: 128,
},
],
strokeColor: [1, 0, 0],
};
Property | Description |
---|---|
points |
Array of { x, y } coordinates.
|
strokeColor |
Array of 3 or 4 color values ranging between 0 and 1 .
|
strokeWidth |
The width of the stroke to use for the path. |
pathClose |
This will draw a line between the first and last point in the points array.
|
State
Property | Description |
---|---|
isSelected |
The shape is currently selected. |
isDraft |
The shape is in draft state, this is true when the shape is being created. |
isComplete |
Is true when all shape resources have loaded. |
isError |
Something went wrong while loading shape resources. |
isLoading |
Currently loading shape resources. |
isEditing |
Currently editing this shape. |
isFormatted |
The shape has been formatted by Pintura Image Editor. |
Right management
Property | Description |
---|---|
disableStyle |
Prevents changing the styles of the shape or disables a selection of styles. |
disableErase |
Prevents erasing the shape with eraser. |
disableSelect |
Prevents selecting the shape. |
disableRemove |
Prevents removing the shape. |
disableDuplicate |
Prevents duplicating the shape. |
disableReorder |
Prevents changing the position of the shape in the shapes list. |
disableFlip |
Prevents flipping the shape. |
disableInput |
Prevents updating the text of the shape or filters the text input. |
disableTextLayout |
Prevents switching text layout. |
disableManipulate |
Prevents manipulating the shape in any way. |
disableMove |
Prevents moving the shape. |
disableResize |
Prevents resizing the shape. |
disableRotate |
Prevents rotating the shape. |
disableTextLayout
If set to true
all text layout options are locked. Set to an array to block specific layout options. Valid values are 'fixed-size'
, 'auto-width'
, and 'auto-height'
This example prevents the text layout from being set to auto height.
const shape = {
x: 0,
y: 0,
width: 128,
height: 128,
text: 'Hello World',
disableTextLayout: ['auto-height'],
};
disableStyle
If set to true
all styles are locked.
Alternatively it can be set to an array of disabled style names.
const shape = {
x: 0,
y: 0,
width: 128,
height: 128,
backgroundColor: [1, 0, 0],
strokeColor: [1, 1, 1],
strokeWidth: 20,
disableStyle: ['strokeWidth', 'strokeColor'],
};
disableInput
Only applies to Text shapes. If set to true
will prevent the user from updating the text
value.
Can alternatively be set to a function
in which case the function receives a string
and can return a formatted string. In the example below we disallow any numeric input.
const shape = {
x: 0,
y: 0,
width: 128,
height: 128,
text: 'Hello World',
disableInput: (text) => text.replace(/[0-9]/g, ''),
};
Colors
Shape colors are defined with an array of 3 or 4 color values.
The array format is [R, G, B]
or [R ,G ,B ,A]
each value ranges between 0
and 1
.
Setting the color red using the RGB
array.
const shape = {
// red
backgroundColor: [1, 0, 0],
// ...other styles
};
Setting an RGBA
value.
// red with 50% opacity
const shape = {
backgroundColor: [1, 0, 0, 0.5],
// ...other styles
};
We can automatically create these arrays from more familiar CSS color values by using the colorStringToColorArray
method exported by the editor.