v8.90.3

Markup Editor Properties

A list of properties available to configure the markup editor.

Property Default value Description
markupEditorToolbar
undefined
An array of tools to render in the Markup Editor toolbar.
markupEditorToolStyles
undefined
The default shape style definitions to use for each tool in the toolbar.
markupEditorToolRetainStyles
undefined
Set to true to remember tool styles between edit sessions.
markupEditorToolShareStyles
undefined
Set to false to have each tool retain its own style settings.
markupEditorShapeStyleControls
undefined
The style control options available to change the appearance of shapes.
markupEditorTextInputMode
'inline'
Set to 'modal' to offer text editing in a plain text modal instead of inline.
markupEditorToolSelectRadius
0
The radius around a select action to select shapes in.
markupEditorWillStartInteraction
undefined
A function that receives the current interaction position and image rectangle, should return true if interaction is allowed and false if not.
markupEditorInteractionMode
'auto'
Set to 'pan' to force pan mode (spacebar + drag), set back to 'auto' to switch to draw mode.
markupEditorZoomLevels
undefined
An array of zoom levels defined as fractions. Default value is [0.25, 0.5, 1, 1.25, 1.5, 2, 3, 4, 6, 8, 16].
markupEditorZoomAdjustStep
.25
The speed at which pressing the zoom buttons increases or decreases zoom.
markupEditorZoomAdjustFactor
.1
The factor used to increase or decrease zoom speed when holding the zoom buttons. Increase speed is 1 + .1, decrease speed is 1 - .1.
enableMultiSelect
false
When set to true enables seleting multiple shapes. Shapes can then be styled and translated simultaneously.
enableSelectToolToAddShape
false
When set to true the editor will add a shape to the middle of the image when a shape tool is tapped.
enableTapToAddText
false
When set to true the editor will add an auto-width text shape when the text tool is active and an empty part of the canvas is tapped.
enableViewTool
false
When set to true a view tool will be added to the tools list, this tool enables dragging the canvas without holding spacebar.
enableMoveTool
false
When set to true a move tool will be added to the tools list, making it easier to move shapes.
enableAutoSelectMoveTool
['path', 'line', 'arrow', 'rectangle', 'ellipse', 'text']
Set to false to disable automatically switching back to the move tool, set to true to enable auto switch back for all shape tools, set to a list of tool keys to pick which tools have this behaviour.
markupEditorSnapThreshold
0
The distance in pixels at which shapes snap to grid or other shapes. When set to 0 snapping is disabled.
markupEditorSnapToContext
true
If enabled shapes snap to context edges and context center.
markupEditorGridSize
0
The size of the grid cells in pixels, when set to 0 the grid is disabled.
beforeSelectShape
undefined
Set to a function that runs before selecting a shape. Receives previously selected shape an targetted shape.
beforeDeselectShape
undefined
Set to a function that runs before deselecting a shape. Receives currently selected shape and targetted shape.
beforeAddShape
undefined
Set to a function that runs before adding a preset shape. Receives shape that is going to be added.
beforeRemoveShape
undefined
Set to a function that runs before removing a shape. Receives shape that is going to be removed. Return true
beforeUpdateShape
undefined
Set to a function that runs before updating a shape. Receives shape that is going to be updated. Additionally receives the props object that will be applied to the shape and the context rectangle in which the shape is rendered.
willRenderShapePresetToolbar
undefined
Can be set to a function to modify the markup editor preset toolbar.
willRenderShapeControls
undefined
Allows to inject custom shape controls or to edit the shape control menu.
willRenderShapeTextControls
undefined
Allows to inject custom shape text controls or to edit the shape text control menu.

markupEditorToolbar

Use the markupEditorToolbar property to update the tools in the Markup Editor toolbar. The property should be set to an array of tool item definitions.

By default the Markup Editor defines the following tools (in this order).

Name Description
'sharpie'
Draw fine lines, this is a path based tool.
'eraser'
Erasing paths, lines, and arrows based lines. Does not have a default shape assigned.
'path'
Draw multi corner path or polygon, hold shift key to snap. Tap start point to close polygon. Tap end point to end path.
'line'
For drawing straight lines, hold shift key to snap.
'arrow'
For drawing arrows, hold shift key to snap.
'rectangle'
For drawing rectangles.
'ellipse'
For drawing ellipses.
'text'
For drawing text boxes.
'preset'
For selecting presets / stickers, only shown if presets have been defined.

The 'eraser' and 'preset' tool are special. Where other tools have a default shape declaration, the preset and eraser tools do not.

The preset tool will show a list of preset stickers, if defined, if not, the preset tool won't be visible. The eraser tool can be used to erase line and path based shapes.

<!DOCTYPE html>

<head>
    <link rel="stylesheet" href="./pintura.css" />
</head>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        markupEditorToolbar: [
            ['sharpie', 'Sharpie', { disabled: true }],
            ['eraser', 'Eraser', { disabled: false }],
            ['rectangle', 'Rectangle', { disabled: false }],
        ],
    });
</script>

We can use the createMarkupEditorToolbar helper function to generate the default toolbar items and make it easier to add our own toolbar items.

If we want to reorder the items but want to retain all default settings we can only use the tool key. In the example below we'll move the Text tool to the first position and have removed the Sharpie and Eraser tools. For more information see the createMarkupEditorToolbar docs.

<!DOCTYPE html>

<head>
    <link rel="stylesheet" href="./pintura.css" />
</head>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import {
        appendDefaultEditor,
        createMarkupEditorToolbar,
    } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        markupEditorToolbar: createMarkupEditorToolbar([
            'text',
            'line',
            'arrow',
            'rectangle',
            'ellipse',
            'preset',
        ]),
    });
</script>

The markup editor toolbar also supports tool groups.

<!DOCTYPE html>

<head>
    <link rel="stylesheet" href="./pintura.css" />
</head>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        markupEditorToolbar: [
            [
                'Draw',
                [
                    ['sharpie', 'Sharpie', { disabled: true }],
                    ['eraser', 'Eraser', { disabled: false }],
                ],
            ],
            [
                'Shape',
                [
                    ['rectangle', 'Rectangle', { disabled: false }][
                        ('ellipse', 'Ellipse', { disabled: false })
                    ],
                ],
            ],
        ],
    });
</script>

markupEditorToolStyles

The markupEditorToolStyles property should be set to an object that describes the default styles for each tool. Each key in this object correlates with a tool key in the toolbar array.

We can use the createMarkupEditorToolStyles helper function to create the default tool styles and to make it easier to generate custom style objects.

<!DOCTYPE html>

<head>
    <link rel="stylesheet" href="./pintura.css" />
</head>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import {
        appendDefaultEditor,
        createDefaultColorOptions,
        createMarkupEditorToolStyle,
        createMarkupEditorToolStyles,
    } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        markupEditorToolStyles: createMarkupEditorToolStyles({
            text: {
                // Increase default font size
                fontSize: '10%',

                // Set default font color to black
                color: createDefaultColorOptions().black,

                // Enable text background color
                backgroundColor: createDefaultColorOptions().transparent,
            },
            rectangle: {
                // Set default color for rectangle background to yellow
                backgroundColor: createDefaultColorOptions().yellow,
            },
        }),
    });
</script>

markupEditorToolRetainStyles

Set markupEditorToolRetainStyles to true to retain style settings between image editing sessions.

Note that when the editor is destroyed the tool styles are lost, this only works when editing and loading images in the same editor instance.

To retain tool styles accross editing sessions we can read out the current tool styles using the 'selectcontrol' and 'selectstyle' events and then set these as default styles using the markupEditorToolStyles property.

markupEditorToolShareStyles

Set to false to have each tool retain its own style settings. Defaults to undefined.

markupEditorShapeStyleControls

The markupEditorShapeStyleControls contains the definitions for the style controls to which are used to adjust the appearance of an active shape.

Each key in the object correlates with a shape style property. The value of the key is set to the component to render and the parameters to send to the component.

{
    backgroundColor: [
        'ColorPicker',
        {
            enableInput: true,
            enableEyeDropper: true,
        }
    ],
    strokeDash: [
        'Dropdown',
        {
            title: 'Line style',
            options: [
                [undefined, 'Solid'],
                [[20, 20], 'Dashed'],
                [[5, 5], 'Dotted'],
            ],
        },
    ],
    // etc
};

Below we use the createMarkupEditorShapeStyleControls helper function to create the default controls.

<!DOCTYPE html>

<head>
    <link rel="stylesheet" href="./pintura.css" />
</head>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import {
        appendDefaultEditor,
        createMarkupEditorShapeStyleControls,
    } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        markupEditorShapeStyleControls: createMarkupEditorShapeStyleControls({
            fontFamilyOptions: [
                ['arial', 'Arial'],
                ['open-sans', 'Open Sans'],
                ['courier', 'Courier'],
            ],
        }),
    });
</script>

When we use one of the default editor factories (openDefaultEditor, or getEditorDefaults) we can pass our shape style controls without calling createMarkupEditorShapeStyleControls

openDefaultEditor({
    markupEditorShapeStyleControls: {
        // Disable a control
        strokeColor: undefined,

        // Only extend/overwrite options
        backgroundColor: {
            options: {
                enableInput: true,
                enableEyeDropper: true,
            },
        },

        // Add a custom control for a style property
        // These can also be custom shapePreprocessor style properties
        strokeDash: [
            'Dropdown',
            {
                title: 'Line style',
                options: [
                    [undefined, 'Solid'],
                    [[20, 20], 'Dashed'],
                    [[5, 5], 'Dotted'],
                ],
            },
        ],
    },
});

willRenderShapePresetToolbar

Use to add custom buttons to the markup editor preset toolbar.

The hook receives 4 parameters:

  • The list of nodes the editor is about to draw.
  • The addPreset callback to add a shape to the current context.
  • The env parameter containing the current environment state.
  • The redraw callback to manually trigger redrawing of the editor UI.

In the example below we create a custom smile button, but this functionality can also be used to import images from third party sources like Dropbox, show modals with custom sticker sources, or open additional editors.

The willRenderShapePresetToolbar hook should always return an array of nodes or an empty array.

<!DOCTYPE html>

<head>
    <link rel="stylesheet" href="./pintura.css" />
</head>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor, createNode, appendNode } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        willRenderShapePresetToolbar: (nodes, addPreset) => {
            // create smile button
            const smileButton = createNode('Button', 'smile-button', {
                label: 'Add smile',
                onclick: () => addPreset('😄'),
            });

            // add it to the node tree
            appendNode(smileButton, nodes);

            // return the new node tree
            return nodes;
        },
    });
</script>

markupEditorTextInputMode

Set to 'modal' to offer text editing in a plain text modal instead of 'inline'.

Please note that 'modal' doesn't support html text style formatting.

markupEditorInteractionMode

Deprecated, use enablePanInput instead.

Set to 'pan' to force pan mode (spacebar + drag), set to 'auto' to switch to draw mode.

markupEditorToolSelectRadius

The radius around a select action to select shapes in, defaults to 0.

markupEditorZoomLevels

Deprecated, use zoomPresetOptions instead.

An array of zoom levels defined as fractions. Default value is [0.25, 0.5, 1, 1.25, 1.5, 2, 3, 4, 6, 8, 16].

markupEditorZoomAdjustStep

Deprecated, use zoomAdjustStep instead.

The speed at which pressing the zoom buttons increases or decreases zoom. Defaults to .25

markupEditorZoomAdjustFactor

Deprecated, use zoomAdjustFactor instead.

The factor used to increase or decrease zoom speed when holding the zoom buttons. Default value is .1, increase speed is 1 + .1, decrease speed is 1 - .1.

enableMultiSelect

When set to true enables seleting multiple shapes. Shapes can then be styled and translated simultaneously.

Snapping, resizing, and rotating multiple shapes is currently not supported.

When a shape in the selection is not allowed to be moved (disableMove is true) the entire selection of shapes will be locked in place.

When a property of a shape in the selection cannot be changed (disableStyle is set) the property cannot be styled for other shapes in the collection.

enableSelectToolToAddShape

When set to true the editor will add a shape to the middle of the image when a shape tool is tapped.

enableTapToAddText

When set to true the editor will add an auto-width text shape when the text tool is active and an empty part of the canvas is tapped.

enableViewTool

When set to true a view tool will be added to the tools list, this tool enables dragging the canvas without holding spacebar.

enableMoveTool

When set to true a move tool will be added to the tools list, making it easier to move shapes.

enableAutoSelectMoveTool

Set to false to disable automatically switching back to the move tool, set to true to enable auto switch back for all shape tools, set to a list of tool keys to pick which tools have this behaviour. Defaults to ['line', 'arrow', 'rectangle', 'ellipse', 'text'].

markupEditorSnapThreshold

The distance in pixels at which shapes snap to grid or other shapes. When set to 0 snapping is disabled.

markupEditorSnapToContext

If enabled shapes snap to context edges and context center.

Use annotateSnapToContext and decorateSnapToContext to alter context snapping per util.

markupEditorGridSize

The size of the grid cells in pixels, when set to 0 the grid is disabled.

Use annotateGridSize and decorateGridSize to alter the grid size per util.

beforeSelectShape

Runs before a shape is selected. Return false to prevent selecting the shape. Receives current selected shape and about to be selected target shape.

If current is undefined it means no shape is currently selected.

<!DOCTYPE html>

<head>
    <link rel="stylesheet" href="./pintura.css" />
</head>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        beforeSelectShape: (current, target) => {
            console.log('beforeSelectShape', current, target);
            return true;
        },
    });
</script>

We can use the beforeSelectShape hook combined with the removeshape event to prevent auto selection of the next shape when a shape was removed.

<!DOCTYPE html>

<head>
    <link rel="stylesheet" href="./pintura.css" />
</head>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor } from './pintura.js';

    let removedShape = undefined;

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        beforeSelectShape: (current) => {
            // if currently selected shape is the shape that was
            // just removed prevent selection of next shape
            return current === removedShape;
        },
    });

    editor.on('removeshape', (shape) => {
        removedShape = shape;
    });
</script>

beforeDeselectShape

Runs before a shape is deselected. Return false to prevent deselecting the shape. Receives current selected shape and about to be selected target shape.

If target is undefined it means no shape is targetted.

<!DOCTYPE html>

<head>
    <link rel="stylesheet" href="./pintura.css" />
</head>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        beforeDeselectShape: (current, target) => {
            console.log('beforeDeselectShape', current, target);
            return true;
        },
    });
</script>

beforeAddShape

Runs before a shape preset is added. Return false to prevent adding the shape.

Instead of using this hook, consider instead disabling the shape tools and sticker items using the disabled property.

This hook only runs when adding shape presets / stickers.

<!DOCTYPE html>

<head>
    <link rel="stylesheet" href="./pintura.css" />
</head>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        beforeAddShape: (shape) => {
            console.log('beforeAddShape', shape);
            return true;
        },
    });
</script>

beforeRemoveShape

Runs before a shape is removed.

Return false to prevent removal of a shape.

<!DOCTYPE html>

<head>
    <link rel="stylesheet" href="./pintura.css" />
</head>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        beforeRemoveShape: (shape) => {
            console.log('beforeRemoveShape', shape);
            return true;
        },
    });
</script>

beforeUpdateShape

Runs before a shape is updated.

Return adjusted props to make changes to shape update.

<!DOCTYPE html>

<head>
    <link rel="stylesheet" href="./pintura.css" />
</head>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        beforeUpdateShape: (shape, props, context) => {
            console.log('beforeUpdateShape', shape, props, context);
            return props;
        },
    });
</script>

willRenderShapeControls

Runs before the shape controls popup is rendered above a selected shape. Allows manipulating the shape controls popup element tree.

The willRenderShapeControls hook receives the current structure of the shape controls popup. The hook allows injecting custom controls into the toolbar using the createNode helper function.

The willRenderShapeControls hook should always return an array. If the returned array is empty the controls are hidden.

<!DOCTYPE html>

<head>
    <link rel="stylesheet" href="./pintura.css" />
</head>

<style>
    .pintura-editor {
        height: 600px;
    }
</style>

<div id="editor"></div>

<script type="module">
    import { appendDefaultEditor } from './pintura.js';

    const editor = appendDefaultEditor('#editor', {
        src: 'image.jpeg',
        willRenderShapeControls: (controls, selectedShapeId) => {
            console.log('willRenderShapeControls', selectedShapeId);

            // Manipulate or add controls here

            return controls;
        },
    });
</script>