Store
Root data model to control canvas, pages, elements, export, and more
Store is a root data model object that you can use to read and control canvas content, check selection, export into different formats and a lot more! It will also provide you with access to Pages and Elements.
import { createStore } from 'polotno/model/store';
const store = createStore({
key: 'YOUR_API_KEY', // you can create it here: https://polotno.com/cabinet/
// you can hide back-link on a paid license
// but it will be good if you can keep it for Polotno project support
showCredit: true,
});
Working with pages
store.addPage()
Store is a set of pages. Each page has elements on it.
const page = store.addPage();
store.pages
Getter. Returns all pages of the store.
store.activePage
Getter. Returns current active (focused) page or the last created.
store.selectPage(id)
Mark a page as active. It will automatically scroll Workspace
to that page. You may think about this method as “focusPage”. For backward compatibility, we keep the original name for now.
// focus second page
store.selectPage(store.pages[1].id);
store.selectedPages
Returns array of currently selected pages. A user may select a page by clicking on its background or from PagesTimeline
component.
store.selectPages(ids)
Mark pages as selected for group actions in PagesTimeline
or visibility of page background properties in the toolbar.
store.selectPages([store.activePage.id]); // show page props in the toolbar
store.selectPages([id1, id2]); // select several pages for highlight in the Timeline
store.deletePages(ids)
Remove pages from the store.
// remove current page
store.deletePages([store.activePage.id]);
store.clear()
Remove all pages from the store.
store.clear(); // it will remove all data and reset undo history
store.clear({ keepHistory: true }); // it will remove all data but keep undo history
UI
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);
store.scale
Getter for current zoom level of the active page.
console.log('zoom is', store.scale);
store.setScale(size)
Change zooming of active page.
store.setScale(2);
store.openedSidePanel
Getter for current opened side panel.
store.previousOpenedSidePanel
Name of the side-panel that was opened before the current one. Useful if you want to open a side panel temporarily for some action then restore the original side panel.
store.openSidePanel(panelName)
Change open side panel manually.
store.openSidePanel('templates');
store.setUnit({ unit, dpi })
Set unit metrics to use in UI.
store.setUnit({
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.
store.unit
Returns unit used in UI to display measures. By default it is px. You can change it to pt, mm, cm, in.
store.dpi
Returns dpi used to convert pixels to other units.
store.toggleBleed()
Show or hide bleed area on the workspace.
store.activePage.set({ bleed: 20 }); // set bleed in pixels
store.toggleBleed();
store.toggleBleed(false);
store.bleedVisible
Getter for current state of bleed visibility.
store.toggleRulers()
Show or hide rulers on workspace.
store.toggleRulers();
store.toggleRulers(false);
store.rulersVisible
Getter for current state of rulers visibility.
store.setRole(role)
Set role of the current user. Possible values are: user
and admin
. For more information see Roles Documentation.
store.setRole('admin');
Working with elements
store.selectedElements
Returns array of currently selected elements on the current page.
const firstSelected = store.selectedElements[0];
store.selectElements(ids)
Selects elements on the canvas by their ids.
store.selectElements([element1.id, element2.id]);
store.deleteElements(ids)
Remove elements from the store.
store.deleteElements([element1.id, element2.id]);
store.getElementById(id)
Finds element in the store by id:
const element = store.getElementById('some-id');
element.set({ x: 0 });
store.groupElements([element1.id, element2.id])
Group elements. It will create a new element with type group
and will move all passed elements inside it.
const ids = store.selectedElements.map((el) => el.id);
store.groupElements(ids);
// optionally you can use second argument to set properties of a group
store.groupElements(ids, { id: 'group-id' });
store.ungroupElements([element1.id, element2.id])
Ungroup elements. It will move all elements inside group to the page and remove the group.
const id = store.selectedElements[0].id;
store.ungroupElements([id]);
History
store.history.canUndo
Can we undo state?
store.history.undo()
Undo last changes
store.activeElements[0].set({ x: 10 });
store.history.undo();
store.history.redo()
Redo changes.
// cancel changes
store.history.undo();
// apply changes again
store.history.redo();
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 NOT create a new history point
element.set({ x: 0, y: 0 });
});
store.history.startTransaction()
Create a new history transaction. After that command all changes will be recorded as one history point.
store.history.endTransaction()
Finish created transaction and record all changes as one history point.
store.history.clear()
Clear history.
Serializations
store.toJSON()
Save store into plain object.
const json = store.toJSON();
// your own function to save JSON somewhere
saveIntoBackend(JSON.stringify(json));
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: https://polotno.com/cabinet/
// you can hide back-link on a paid license
// 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);
store.loadJSON(json);
// load JSON but save previous undo history
// a user can undo this action
store.loadJSON(json, true);
Events
store.on('change', () => {})
Listen to any changes in the store. The event may trigger frequently on some operations like resize or dragging. store.on()
returns an unsubscribe function.
// unsubscribe function
const off = store.on('change', () => {
console.log('something changed');
});
// that line will unsubscribe from the event
off();
// write a function for throttle saving
let timeout: any = null;
const requestSave = () => {
// if save is already requested - do nothing
if (timeout) {
return;
}
// schedule saving to the backend
timeout = setTimeout(() => {
// reset timeout
timeout = null;
// export the design
const json = store.toJSON();
// save it to the backend
fetch('https://example.com/designs', {
method: 'POST',
body: JSON.stringify(json),
});
}, 1000);
};
// request saving operation on any changes
store.on('change', () => {
requestSave();
});
Export
store.waitLoading()
Wait until all resources (images, fonts, etc) are loaded and displayed on the canvas.
// import data
store.loadJSON(json);
// 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 });
// make small export for preview
// quickMode will skip some "perfect rendering" calculations
await store.toDataURL({ pixelRatio: 0.2, quickMode: true });
// ignore page background on export
await store.toDataURL({ ignoreBackground: true });
// export as jpg
await store.toDataURL({ mimeType: 'image/jpeg' });
// export only required page
await store.toDataURL({ pageId: store.pages[1].id });
// export with page bleed
await store.toDataURL({ includeBleed: true });
await store.saveAsImage()
saveAsImage
will export the drawing into an image and download it as a local file. By default, it exports just the first page. If you need to export other pages, pass pageId
property.
// default export
store.saveAsImage({ fileName: 'polotno.png' });
// export as jpg
store.saveAsImage({ mimeType: 'image/jpeg' });
// 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 });
// export with page bleed
store.saveAsImage({ includeBleed: true });
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 });
// export only sub set of pages
await store.toPDFDataURL({ pageIds: [store.pages[0].id, store.pages[2].id] });
// export with page bleed and crop marks
await store.toPDFDataURL({ includeBleed: true, cropMarkSize: 20 });
// track progress
await store.toPDFDataURL({ onProgress: (progress) => console.log(progress) });
await store.saveAsPDF()
saveAsPDF
will export the drawing into PDF and download it as a local file. By default, it exports just the first page. If you need to export other pages, pass pageId
property.
// default export
await store.saveAsPDF({ fileName: 'polotno.pdf' });
// change default dpi
// changing DPI will not affect quality of the export. But it may change page size of exported PDF
await store.saveAsPDF({ dpi: 300 }); // default is store.dpi, it equals 72
// ignore page background on export
await store.saveAsPDF({ ignoreBackground: true });
// change export quality
await store.saveAsPDF({ pixelRatio: 2 });
// export with page bleed
await store.saveAsPDF({ includeBleed: true });
// export with page bleed and crop marks
await store.saveAsPDF({ includeBleed: true, cropMarkSize: 20 });
// export only sub set of pages
await store.saveAsPDF({ pageIds: [store.pages[0].id, store.pages[2].id] });
// track progress
await store.saveAsPDF({ onProgress: (progress) => console.log(progress) });
await store.toBlob()
Export store into blob object, it may work faster than toDataURL
method.
// default export
await store.toBlob();
// make exported image 2x bigger (higher quality)
await store.toBlob({ pixelRatio: 2 });
// ignore page background on export
await store.toBlob({ ignoreBackground: true });
// export as jpg
await store.toBlob({ mimeType: 'image/jpeg' });
// export only required page
await store.toBlob({ pageId: store.pages[1].id });
// export with page bleed
await store.toBlob({ includeBleed: true });
await store.toHTML()
Warning: this function is beta and may produce inconsistent result.
Export store into HTML string.
const html = await store.toHTML();
const html2 = await store.toHTML({
elementHook: ({ dom, element }) => {
// post process dom representation of the element
// it is a lite jsx-like object
// it should have "type", "props" and "children"
console.log(dom); // first you can log it to see what is inside
// then you can mutate it based on your custom logic
dom.props.className = 'my-element';
return dom;
},
});
await store.saveAsHTML()
Warning: this function is beta and may produce inconsistent result.
Export store into HTML string and download it as local .html
file.
await store.toSVG()
Warning: this function is beta and may produce inconsistent result.
Export store into SVG string.
const svg = await store.toSVG({
fontEmbedding: 'inline', // "inline" or "none"
elementHook: ({ dom, element }) => {
// post process dom representation of the element
dom.className = 'my-element';
return dom;
},
});
await store.saveAsSVG()
Export store into SVG string and download it as local .svg
file.
await store.toGIFDataURL()
Export store into GIF image in base64 URL format.
// default GIF export
const url1 = await store.toGIFDataURL();
// export with full control and progress tracking
const url2 = await store.toGIFDataURL({
// GIF-specific option
fps: 10,
// control size/quality of the exported GIF
pixelRatio: 1,
});
await store.saveAsGIF()
saveAsGIF
will export drawing into GIF and download it as local file.
// or save directly as a file with similar options
await store.saveAsGIF({
fileName: 'polotno.gif',
fps: 10,
pixelRatio: 2,
});
store.setElementsPixelRatio(ratio)
In most scenarios Polotno is rasterizing (converting into bitmap) vector elements such as texts and SVG images. When you do high quality exports, you may want to temporarily increase resolution of rendered elements.
// make sure all elements are rendered with increased quality
store.setElementsPixelRatio(2);
// do the export
await store.toDataURL({ pixelRatio: 2 });
Animations and video
store.play()
Preview animations inside the workspace
// start playing
store.play();
// start from a specific time
store.play({ startTime: 10000 });
// automatically pause on a specific time
store.play({ endTime: 10000 });
// animate only selected elements
store.play({ animatedElementsIds: store.selectedElements.map((el) => el.id) });
// loop play
store.play({ repeat: true });
store.stop()
Stop all animations, reset the current time
store.currentTime
Returns current time of playback
store.setCurrentTime()
Seek to a specific time
Working with audio
store.addAudio({ src })
Add audio into the design
store.addAudio({
src: 'https://example.com/audio.mp3',
// optional props:
startTime: 0, // define relative point in time of original sound to start the play.
endTime: 1, // define relative point in time of original sound to stop the play.
volume: 1, // from 0 to 1
delay: 0, // in ms the duration between start of video (final scene) and audio play time
});
store.addAudio({
src: 'https://example.com/audio.mp3',
delay: 10000, // the audio will start to play after 10 seconds of video
startTime: 0.5, // if audio duration is 1 min, then we will start to hear it from its 30 secs
});
store.removeAudio(audioId)
Remove audio by its id
store.audios
Access array of added audios of the scene
store.audios.map((audio) => {
console.log(audio.id, audio.src);
});
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.
store.addFont({
fontFamily: 'MyCustomFont',
url: serverUrlOrBase64,
});
Also you can use a richer API for more control:
store.addFont({
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:
store.addFont({
fontFamily: 'MyCustomFont',
});
store.removeFont(name)
Remove custom font from the store by its name
store.removeFont('MyCustomFont');
store.loadFont(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.loadFont(name)
function will add font to the webpage, so the browser can render correct font.