This is the archived documentation for Doka Image Editor v7.

Please visit pqina.nl/pintura/docs/ to see documentation for the latest version of Pintura Image Editor.

Editor properties

Doka Image Editor exposes a set of properties that enable us to update the editor state.

Editor properties

These read only properties are available on the editor instance.

Property Default value Description
element
HTMLElement
The root element of the editor.
modal
HTMLElement
The root element of the modal. Only available when the editor was created with the openEditor method.

These read/write properties are available on the editor instance.

Property Default value Description
id
undefined
The id attribute set to the editor root element.
class
undefined
The class attribute set to the editor root element.
src
undefined
The image source to load, can be of type File, Blob, DataURL, URL, HTMLCanvasElement, or HTMLImageElement.
locale
undefined
The locale object to use for the editor labels.
utils
undefined
The enabled utils and their order in the menu.
util
undefined
The active util, is automatically set to first util in utils array.
layoutDirectionPreference
'auto'
The direction preference of the editor layout, when is 'auto' the editor will automatically set it to 'vertical' for when the editor root is in portrait aspect ratio and 'horizontal' for landscape aspect ratio.
animations
'auto'
Control if and when animations are shown.
elasticityMultiplier
10
Controls the elasticity force of the interface.
previewUpscale
false
Should the image preview be upscaled to fit the editor stage.
previewImageDataMaxSize
undefined
Maximum texture size to use for the preview image. Will default to browser max texture size.
imageSourceToImageData
undefined
The function to use for preview reading image data.
imageOrienter
undefined
The object to use to correctly orient preview image data.
imageReader
undefined
The imageReader to use for reading image data.
imageWriter
undefined
The imageWriter to use for writing image data.
enableToolbar
true
Set to false to disable the toolbar.
enableUtils
true
Set to false to disable the util tabs.
enableButtonClose
false
Set to true to show a close button, automatically set to true when using openModal.
enableButtonExport
true
Set to false to disable the export button.
enableButtonRevert
true
Set to false to disable the history revert button.
enableNavigateHistory
true
Set to false to disable the undo and redo buttons.
enableDropImage
false
Set to true to allow loading a new image by dropping it on the editor.
handleEvent
undefined
A function that is called for each event. Receives event type and detail.
willRenderCanvas
undefined
Inject shapes or adjust shapes in the image preview.
willRenderToolbar
undefined
Inject custom buttons into the editor toolbar.
willRevert
undefined
Prevent revert action.

src

The source image to load. Update to load a new image.

Accepts:

  • File
  • Blob
  • DataURL
  • URL
  • HTMLCanvasElement
  • HTMLImageElement

Due to browser security restrictions loading remote URLs is only possible if the remote location has properly configured CORS headers.

import { openEditor } from './doka.js';

openEditor({
    src: './my-image.jpeg',
});

locale

The editor requires the locale property to be set to a valid locale object.

In the example below we assign the core editor locale and the crop plugin locale object.

import { openEditor, locale_en_gb, plugin_crop_locale_en_gb } from 'doka.js';

// Merge the locale objects
const myLocale = {
    ...locale_en_gb,
    ...plugin_crop_locale_en_gb,
};

// Assign locale to editor
openEditor({
    src: 'my-image.jpeg',
    locale: myLocale,
});

See below for an example of the locale_en_gb object exported by the editor module.

{
    labelDefault: 'Default',
    labelReset: 'Reset',
    labelAuto: 'Auto',
    labelNone: 'None',
    labelEdit: 'Edit',
    labelClose: 'Close',

    // etc...
}

To change a label we can update one of the properties in the locale object.

// Merge the locale objects
const myLocale = {
    ...locale_en_gb,
    ...plugin_crop_locale_en_gb,
};

// Change label of export button to 'Save'
myLocale.labelButtonExport = 'Save';

The code below logs all locale properties to the developer console so we can easily see which property to edit if we need to change labels or icons.

import {
    // core locale
    locale_en_gb,

    // plugin locale
    plugin_crop_locale_en_gb,
    plugin_finetune_locale_en_gb,
    plugin_filter_locale_en_gb,
    plugin_annotate_locale_en_gb,
    plugin_decorate_locale_en_gb,
    plugin_resize_locale_en_gb,
    plugin_sticker_locale_en_gb,

    // markup editor locale
    markup_editor_locale_en_gb,
} from './doka.js';

// log merged objects to console
console.log({
    ...locale_en_gb,
    ...plugin_crop_locale_en_gb,
    ...plugin_finetune_locale_en_gb,
    ...plugin_filter_locale_en_gb,
    ...plugin_annotate_locale_en_gb,
    ...plugin_decorate_locale_en_gb,
    ...plugin_resize_locale_en_gb,
    ...plugin_sticker_locale_en_gb,
    ...markup_editor_locale_en_gb,
});

A reference to the modal wrapping the editor. This property is only available when the editor is created with openEditor.

util

Updates the current active util and will trigger the editor to show the corresponding view.

doka.util = 'finetune';

utils

Use to set which utils are shown and in what order they appear in the editor menu.

doka.utils = ['crop', 'filter', 'finetune'];

animations

Toggle if and when the editor runs animations.

'auto'
Will enable animations if user hasn't specified prefers reduced motion in system settings.
'never'
Disables all animations.
'always'
Will set the editor to ignore user preferences and always run animations.

previewUpscale

If set to true the preview image will be scaled to fit the editor stage.

If false the preview image will only be scaled down to fit the stage, if the preview image is smaller than the stage it will not be upscaled.

This only affects the preview of the image in the editor, this won't affect the size of the output image.

imageSourceToImageData

A helper method to correctly read custom preview image data.

The image formats that Doka can read and write depend on which images are supported by the clients browser. In general these image types are supported by all major browsers.

  • image/gif
  • image/png
  • image/jpeg
  • image/webp
  • image/bmp
  • image/svg

If we want to be able to read additional image formats (for example HEIC/HEIF) inside the editor we can supply our own image reader using the imageSourceToImageData property.

Please note that this function is used for all image resources inside the editor, if we only need to load additional image formats for editing it's better to set the preprocessImageFile hook of the imageReader property.

const app = openEditor({
    // Custom imageSourceToImageData method
    imageSourceToImageData: (src) =>
        fetch(src)
            .then((res) => res.blob())
            .then((blob) => {
                return new Promise((resolve, reject) => {
                    // Turn blob into image data here

                    // resolve with ImageData object
                    resolve(imageData);
                });
            }),
});

imageOrienter

Can be set to a helper object to correctly orient image data. This is useful for older browsers where interpretation of the EXIF orientation header is done incorrectly and images appear upside down or mirrored.

The property expects an object with an read and an apply function.

  • The read function is used to read the EXIF orientation header from the image preview data.
  • The apply function is used to apply the EXIF orientation header to the image preview.

We can import the createDefaultImageOrienter method and use it to set the imageOrienter property to automatically orient images.

import { createDefaultImageOrienter } from './doka.js';

const app = openEditor({
    imageOrienter: createDefaultImageOrienter(),
});

imageReader

Expects an array of read steps to step through when reading the src input image data.

We can import the createDefaultImageReader method and use it to set the imageReader property to read preview images.

import { openEditor, createDefaultImageReader } from './doka.js';

openEditor({
    imageReader: createDefaultImageReader(),
});

The imageReader property has to be set for the editor to be able to show image previews, without it the editor won't run.

imageWriter

Expects an array of write steps to step through when writing the output image data.

We can import the createDefaultImageWriter method and use it to set the imageWriter property to write output images.

import { openEditor, createDefaultImageWriter } from './doka.js';

openEditor({
    imageWriter: createDefaultImageWriter(),
});

If we don't need to output image data, for example when we're only storing the original image and the editor state, we don't have to set the imageWriter property.

handleEvent

Set to a function to route events. The handleEvent callback runs for each public event the editor dispatches, it receives the event type and detail.

Overview of all editor events

import { openEditor } from './doka.js';

openEditor({
    handleEvent: (type, detail) => {
        // log all editor events to console
        console.log(type, detail);
    },
});

willRevert

Set to an async method.

Resolve with false to prevent the revert of all user actions, resolve with true to revert the editor to the initial state.

import { openEditor } from './doka.js';

openEditor({
    willRevert: () =>
        new Promise((resolve) => {
            /* determine if should revert */

            resolve(false); // false will cancel revert action
        }),
});

willRenderCanvas

We can use the willRenderCanvas hook to alter what Doka renders to the screen.

The willRenderCanvas hook receives two parameters, the shapes that are about to be drawn, and the current state.

Example draw state object.

{
    // is user currently interacting
    isInteracting: false,

    // will animate from 0 to 1 when interacting
    isInteractingFraction: 0,

    // opacity of the image from 0 to 1
    opacity: 1,

    // rotation of image
    rotation: {
        x: 0,
        y: 0,
        z: 0,
    },

    // scale of image
    scale: 0.615625,

    // size of canvas
    size: {
        width: 1040,
        height: 510,
    },

    // foreground color of canvas
    foregroundColor: [0, 0, 0],

    // background color of canvas
    backgroundColor: [1, 1, 1],

    // line color used in canvas
    lineColor: [0, 0, 0],

    // rectangle of editor root
    rootRect: {
        x: 0,
        y: 0,
        width: 1040,
        height: 510,
    },

    // rectangle of crop selection
    selectionRect: {
        x: 322,
        y: 60,
        height: 394,
        width: 522,
    },

    // rectangle of util
    stageRect: {
        x: 144,
        y: 60,
        width: 880,
        height: 394,
    },

    // opacity of each util, from 0 to 1
    utilVisibility: {
        annotate: 0,
        crop: 1,
        decorate: 0,
        filter: 0,
        finetune: 0,
        resize: 0,
        sticker: 0,
    },
};

Example shapes object.

{
    // these are drawn relative to the preview image
    annotationShapes: [
        {
            backgroundColor: [0, 1, 1],
            cornerRadius: 0,
            disableErase: true,
            height: 200,
            id: 'dgyf5b4cu',
            opacity: 1,
            rotation: 0,
            strokeColor: [0, 0, 0],
            strokeWidth: 0,
            width: 200,
            x: 20,
            y: 20,
        },
    ],

    // these are drawn relative to the crop selection
    decorationShapes: [],

    // these are drawn on top of the user interface
    interfaceShapes: [
        {
            id: 'image-selection-guide-row-0',
            opacity: 1,
            points: [
                { x: 322.475, y: 60 },
                { x: 844.525, y: 60 },
            ],
            strokeColor: [0, 0, 0],
            strokeWidth: 1,
        },
        // ...and some more shapes
    ],
};

In the snippet below we draw a circular overlay on top of the crop selection, see crop overlay example for a live preview.

import { openEditor } from './doka.js';

openEditor({
    // this method is synchronouse,
    // it's called before each render
    willRenderCanvas: (shapes, state) => {
        const { utilVisibility, selectionRect, backgroundColor, lineColor } =
            state;

        // exit if crop utils is not visible
        if (utilVisibility.crop <= 0) return shapes;

        // shortcuts to selection rect
        const { x, y, width, height } = selectionRect;

        // return updated shapes
        return {
            // copy props from shapes param
            ...shapes,

            // add an `ellipse` shape
            interfaceShapes: [
                {
                    x: x + width * 0.5,
                    y: y + height * 0.5,
                    rx: width * 0.5,
                    ry: height * 0.5,
                    opacity: utilVisibility.crop,
                    inverted: true,
                    backgroundColor: [...backgroundColor, 0.5],
                    strokeWidth: 1,
                    strokeColor: [...lineColor],
                },
                ...shapes.interfaceShapes,
            ],
        };
    },
});

willRenderToolbar

This is an experimental feature, the API isn't final yet and might be changed in a future release.

The willRenderToolbar hook receives the current toolbar definition and editor environment parameters. The hook allows injecting custom controls into the toolbar.

The method should always return the received toolbar. If an empty array is returned the toolbar is hidden.

import { openEditor } from './doka.js';

openEditor({
    willRenderToolbar: (toolbar, env, redraw) => {
        console.log(toolbar);
        // logs: [ Array(4), Array(4), Array(4) ]

        console.log(env);
        // logs: { orientation: "landscape", verticalSpace: "short", … }

        return toolbar;
    },
});

A toolbar item can either be a tag or a Svelte component. Each item needs to have a unique id. Children are only supported on the tag descriptor.

// tag
const toolbarItems = [
    // html tag item
    [
        'div', // only div is supported
        'my-unique-id',
        {
            class: 'my-class-name',
        },
        [
            // Svelte component item
            [
                SvelteComponent,
                'my-unique-id',
                {
                    label: 'Label',
                },
            ],
            // other children
        ],
    ],
    // other top level items
];

Image properties

Readonly image properties

Property Description
imageFile The image source as a File object.
imageSize The natural size of the image.
imageLoadState The load state of the image.
imageProcessState The processing state of the image.
imageAspectRatio The aspect ratio of the image.
imageCropRectAspectRatio The aspect ratio of the crop rectangle.
imageCropSize The size of the crop rectangle.
imageRotationRange The min and max rotation of the image.

Image properties to update image state

Property Default value Description
imageCrop
undefined
A Rect describing the crop relative to the bounding box of the rotated image.
imageRotation
0
The rotation of the image in radians.
imageCropAspectRatio
undefined
Set the aspect ratio of the crop as a number.
imageCropLimitToImage
true
Set to true to limit the crop to the image edges.
imageCropMinSize
{ width:1, height:1 }
A Size describing The minimum size of the crop.
imageCropMaxSize
undefined
An array [width, height] describing the maximum size of the crop. By default the editor determines the max size based on the browser.
imageFlipX
false
Flip image over X axis.
imageFlipY
false
Flip image over Y axis.
imageTargetSize
undefined
A Size describing the output size of the image.
imageAnnotation
[]
Set to an array of shapes to apply to the image.
imageDecoration
[]
Set to an array of shapes to apply to the crop.
imageBackgroundColor
undefined
The background color to use for the output image, defaults to transparent. Will render black for non-transparent image formats.
imageColorMatrix
undefined
A color matrix to apply to the image.
imageGamma
undefined
The image gamma adjustment.
imageVignette
undefined
Vignette to apply to the image -1 to 1.
imageState
undefined
The current state of the image, this contains all information to recreate the current image state.

imageLoadState

The imageLoadState contains the load state of the current image as it is passed through the imageReader.

imageProcessState

The imageProcessState contains the process state of the current image as it is passed through the imageWriter.

imageCrop

The current crop rectangle is relative to the (optionally rotated) bounding box of the image.

In the diagram below we can see how this works. We've defined a 64 x 64 crop in the top left corner of the image.

  • The dashed line illustrates the bounding box of the rotated image.
  • The magenta square represents our 64 × 64 crop positioned relative to the image bounding box.

We can see how the crop rectangle updates when we rotate the image using the range input.

If we assign options to the editor creation command the crop will be set first and then the rotation. In the example below, no matter the order of the properties, the crop will be set first and then the image will be rotated.

import { openEditor, degToRad } from './doka.js';

openEditor({
    // 2. Rotate the image
    imageRotation: degToRad(45),

    // 1. Crop 64 x 64 image from top left corner
    imageCrop: {
        x: 0,
        y: 0,
        width: 64,
        height: 64,
    },
});

imageCropAspectRatio

Set the aspect ratio of the crop as a number. Set to undefined to not enforce a crop aspect ratio.

import { openEditor } from './doka.js';

openEditor({
    imageCropAspectRatio: 16 / 9,
});

imageCropLimitToImage

When set to true Doka will prevent cropping outside of the image edges.

When set to false we can make a crop outside of the image edges. This also means we can zoom out further and rotate the image without auto zoom. To control the background color of pixels outside of the image we can set the imageBackgroundColor prop.

imageBackgroundColor

Set the background color to use for the output image and the image preview in the editor.

import { degToRad } from './doka.js';

openEditor({
    // set to red
    imageBackgroundColor: [1, 0, 0],
});

If we like a more familiar way of setting colors we can use the colorStringToColorArray method exported by the Doka Image Editor module.

Transparent background colors are supported in the output image but the preview isn't rendered correctly in the editor.

imageState

The imageState property describes the current image state.

See below for an example:

{
    // transforms
    flipX: false,
    flipY: false,
    rotation: 0,
    crop: { x: 0, y: 0, width: 1024, height: 768 },
    cropAspectRatio: undefined,
    cropMinSize: { width: 1, height: 1 },
    cropMaxSize: { width: 32767, height: 32767 },
    cropLimitToImage: true,

    // shapes
    annotation: [
        {
            id: 'lme6159vp',
            x: 32,
            y: 64,
            width: 320,
            height: 256,
            backgroundColor: [1, 0, 0],
            strokeColor: [1, 1, 1, 0],
            strokeWidth: 0,
            cornerRadius: 0,
        }
    ],
    decoration: [],

    // filters
    colorMatrix: undefined,
    convolutionMatrix: undefined,
    gamma: undefined,
    vignette: undefined,

    // output
    backgroundColor: [0, 0, 0, 0],
    targetSize: undefined,
}

Markup editor properties

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.
markupEditorShapeStyleControls
undefined
The style control options available to change the appearance of shapes.
markupEditorToolSelectRadius
0
The radius around a select action to select shapes in.
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 edit the shape 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.
'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.

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

import { openEditor } from './doka.js';

openEditor({
    markupEditorToolbar: [
        ['sharpie', 'Sharpie', { disabled: true, icon: '<g></g>' }],
        ['eraser', 'Eraser', { disabled: false, icon: '<g></g>' }],
        ['rectangle', 'Rectangle', { disabled: false, icon: '<g></g>' }],
    ],
});

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 createMarkupEditorToolStyle and createMarkupEditorToolStyles helper function to set the default tool styles and to make it easier to generate custom style objects.

import {
    openEditor,
    createMarkupEditorToolStyles,
    createMarkupEditorToolStyle,
} from './doka.js';

openEditor({
    // create the default tool styles
    markupEditorToolStyles: createMarkupEditorToolStyles({
        // create the text tool style and override fontSize property
        text: createMarkupEditorToolStyle('text', {
            fontSize: '10%',
        }),
    }),
});

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.

We can use the createMarkupEditorShapeStyleControls helper function to generate the default controls and to make it easier to generate custom style control objects.

import { openEditor } from './doka.js';

openEditor({
    markupEditorShapeStyleControls: {
        backgroundColor: [
            ColorPicker, // component
            {}, // settings
        ],
        fontFamily: [
            Dropdown, // component
            {}, // settings
        ],
        // ...
    },
});

willRenderShapePresetToolbar

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

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.

import { openEditor, createNode } from './doka.js';

openEditor({
    willRenderShapePresetToolbar: (nodes, addPreset, env) => {
        // create smile button
        const smileButton = createNode('Button', 'smile-button', {
            label: 'Add smile',
            onclick: () => addPreset('😄'),
        });

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

        // return the new node tree
        return nodes;
    },
});

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.

import { openEditor } from './doka.js'

openEditor({
    beforeSelectShape = (current, target) => {
        console.log('beforeSelectShape', target);
        return true;
    }
});

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

import { openEditor } from './doka.js'

let removedShape;

const editor = openEditor({
    beforeSelectShape = (current, target) => {
        // if currently selected shape is the
        // shape that was just removed prevent selection
        // of next shape
        if (current === removedShape) return false;

        return true;
    }
});

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

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.

import { openEditor } from './doka.js'

openEditor({
    beforeDeselectShape = (current, target) => {
        console.log('beforeDeselectShape', current);
        return true;
    }
});

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.

import { openEditor } from './doka.js'

openEditor({
    beforeAddShape = (shape) => {
        console.log('beforeAddShape', shape);
        return true;
    }
});

beforeRemoveShape

Runs before a shape is removed.

Return false to prevent removal of a shape.

import { openEditor } from './doka.js'

openEditor({
    beforeRemoveShape = (shape) => {
        console.log('beforeRemoveShape', shape);
        return true;
    }
});

beforeUpdateShape

Runs before a shape is updated.

Return adjusted props to make changes to shape update.

import { openEditor } from './doka.js'

openEditor({
    beforeUpdateShape = (shape, props, context) => {
        console.log('beforeUpdateShape', shape, props, context);
        return props;
    }
});

willRenderShapeControls

This is an experimental feature, the API isn't final yet and might be changed in a future release.

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

import { openEditor } from './doka.js'

openEditor({
    willRenderShapeControls = (controls, selectedShapeId) => {

        // manipulate shape controls here

        return controls;
    }
});