Skip to main content


Store is a basic data model object they you are going to work with. It has about %90 API functions provided by Polotno.

Working with pages

import { createStore } from 'polotno/model/store';
const store = createStore({
key: 'YOUR_API_KEY', // you can create it here:
// you can hide back-link on a paid licence
// but it will be good if you can keep it for Polotno project support
showCredit: true,


Store is a set of pages. Each pages have elements on it.

const page = store.addPage();


The getter. Returns all pages of the store.


The getter. Returns current active page or the last created.


Mark a page as active. It will automatically scroll <Workspace /> to that page.

// select second page


Remove pages from the store

// remove current page


store.width and store.height

Returns size of every page.

console.log('Width is', store.width);

store.setSize(width, height, shouldUseMagicResize?)

Set new size of every page in the store

// just change the pages size
store.setSize(1000, 500);

// resize all pages and apply "magic resize"
// magic resize will automatically change sizes of all elements and adjust their position for a new size
store.setSize(1000, 500, true);


Getter for current zoom level of the active page.

console.log('zoom is', store.scale);


Change zooming of active page.



Getter for current opened side panel


Change open side panel manually.


store.setUnit({ unit, dpi })

Set unit metrics to use in UI.

unit: 'mm', // mm, cm, in, pt, px
dpi: 300,

Important! Setting new unit will NOT change values in store and elements attributes, such as width, height, x, y, fontSize! They will still be saved in pixels. Unit metrics will be used only for default UI from Polotno.


Returns unit used in UI to display measures. By default it is px. You can change it to pt, mm, cm, in.


Returns dpi used to convert pixels to other units.

Working with elements


Returns array of currently selected elements on the current page

const firstSelected = store.selectedElements[0];


Selects elements on the canvas by their ids.



Remove elements from the store.



Finds elements on the store by passed id:

const element = store.getElementById('some-id');
element.set({ x: 0 });



Can we undo state?


Undo last changes

store.activeElements[0].set({ x: 10 });


Can we redo state?


Redo changes.

// cancel changes

// apply changes again

store.history.transaction(async () => {})

Batch several actions into one history entry.

store.history.transaction(async () => {
const element = store.activePage.addElement({
type: 'text',
text: 'loading',
const text = await serverRequest();
element.set({ text });

store.history.ignore(async () => {})

Run transaction that should be ignored in history

store.history.ignore(() => {
// that change will be NOT create new history point
element.set({ x: 0, y: 0 });


Create a new history transaction. After that command all changes will be recorded as one history point.


Finish created transaction and record all changes as one history point.



Save store into plain object.

const json = store.toJSON();

// your own function to save JSON somewhere

store.loadJSON(json, keepHistory?)

Load passed json into the store. It will update all properties, pages and elements. By default loading JSON into the store will reset undo/redo history (so a user can't undo it). You can use keepHistory argument, if you want to preserve the history.

import { createStore } from 'polotno/model/store';
const store = createStore({
key: YOUR_API_KEY, // you can create it here:
// you can hide back-link on a paid licence
// but it will be good if you can keep it for Polotno project support
showCredit: true,

// save to JSON at some point of time
const json = store.toJSON();

// load from JSON
// remember that "json" should be a javascript object
// if you have a json string, you may need to parse it - JSON.parse(string);

// load JSON by save previous undo history
// a user can undo this action
store.loadJSON(json, true);


store.on('change', () => {})

Listen to any changes in the store. The event may trigger frequently on some operations like resize or dragging.

// write a function for throttle saving
let timeout = null;
const requestSave = () => {
// if save is already requested - do nothing
if (timeout) {
// schedule saving to the backend
timeout = setTimeout(() => {
// reset timeout
timeout = null;
// export the design
const json = store.toJSON();
// save it to the backend
fetch('', {
method: 'POST',
body: JSON.stringify(json),
}, 1000);

// request saving operation on any changes
store.on('change', () => {



Wait until all resources (images, fonts, etc) are loaded and displayed on the canvas.

// import data
// wait for loading
await store.waitLoading();
// do export
const url = await store.toDataURL();

await store.toDataURL()

Export store into image in base64 URL format

// default export
await store.toDataURL();

// make exported image 2x bigger (higher quality)
await store.toDataURL({ pixelRatio: 2 });

// ignore page background on export
await store.toDataURL({ ignoreBackground: true });

// export as jpg
await store.toDataURL({ mimeType: 'image/jpg' });

// export only required page
await store.toDataURL({ pageId: store.pages[1].id });


saveAsImage will export drawing into image and save it as local file. By default it exports just the first page. If you need to export another pages, pass pageId property.

// default export
store.saveAsImage({ fileName: 'polotno.png' });

// export as jpg
store.saveAsImage({ mimeType: 'image/jpg' });

// make exported image 2x bigger (higher quality)
store.saveAsImage({ pixelRatio: 2 });

// ignore page background on export
store.saveAsImage({ ignoreBackground: true });

// export second page
store.saveAsImage({ pageId: store.pages[1].id });

async store.toPDFDataURL()

Export store into PDF file in base64 URL format. You can use it to save to the backend.

// default export
await store.toPDFDataURL();

// double exported quality
await store.toPDFDataURL({ pixelRatio: 2 });

// ignore page background on export
await store.toPDFDataURL({ ignoreBackground: true });


saveAsPDF will export drawing into PDF and save it as local file. By default it exports just the first page. If you need to export another pages, pass pageId property.

// default export
store.saveAsPDF({ fileName: 'polotno.pdf' });

// change default dpi
// changing DPI will not effect quality of the export. But it may change page size of exported PDF
store.saveAsPDF({ dpi: 300 }); // default is store.dpi, it equals 72

// ignore page background on export
store.saveAsPDF({ ignoreBackground: true });

// change export quality
store.saveAsPDF({ pixelRatio: 2 });


In most of scenarios polotno is rasterizing (converting into bitmap) vector elements such as texts and svg images. When you do hight quality exports, you may want to temporary increase resolution of rendered elements.

// make sure all elements are rendered with increased quality
// do the export
await store.toDataURL({ pixelRatio: 2 });

Working with fonts

store.addFont({ fontFamily, url })

The function to add a new custom font to the user project. Added fonts will be saved into exported JSON. If you want to add fonts available globally (ignored in JSON export), take a look into Fonts Tutorial.

fontFamily: 'MyCustomFont',
url: serverUrlOrBase64,

Also you can use a richer API for more control:

fontFamily: 'MyCustomFont',
styles: [
src: 'url(pathToNormalFile.ttf)',
fontStyle: 'normal',
fontWeight: 'normal',
src: 'url(pathToBoldFile.ttf)',
fontStyle: 'normal',
fontWeight: 'bold',

Or you can just register font in the store and then manually add required CSS into the page:

fontFamily: 'MyCustomFont',


Remove custom font from the store by its name



Prepare the font to use on the webpage. Text elements inside <Workarea> will use this function automatically. But it can be useful if you want to show a list of fonts somewhere in the UI. store.loadFond(name) function will add font to the webpage, so the browser can render correct font.