Skip to main content

Creating Elements programmatically

We support a simplified API to make it easier to generate Excalidraw elements programmatically. This API is in beta and subject to change before stable. You can check the PR for more details.

For this purpose we introduced a new type ExcalidrawElementSkeleton. This is the simplified version of ExcalidrawElement type with the minimum possible attributes so that creating elements programmatically is much easier (especially for cases like binding arrows or creating text containers).

The ExcalidrawElementSkeleton can be converted to fully qualified Excalidraw elements by using convertToExcalidrawElements.

convertToExcalidrawElements

Signature

convertToExcalidrawElements(
elements: ExcalidrawElementSkeleton,
opts?: { regenerateIds: boolean }
): ExcalidrawElement[]
NameTypeDefaultDescription
elementsExcalidrawElementSkeletonThe Excalidraw element Skeleton which needs to be converted to Excalidraw elements.
opts{ regenerateIds: boolean } {regenerateIds: true}By default id will be regenerated for all the elements irrespective of whether you pass the id so if you don't want the ids to regenerated, you can set this attribute to false.

How to use

import { convertToExcalidrawElements } from "@excalidraw/excalidraw";

This function converts the Excalidraw Element Skeleton to excalidraw elements which could be then rendered on the canvas. Hence calling this function is necessary before passing it to APIs like initialData, updateScene if you are using the Skeleton API

Supported Features

Rectangle, Ellipse, and Diamond

To create these shapes you need to pass its type and x and y coordinates for position. The rest of the attributes are optional_.

For the Skeleton API to work, convertToExcalidrawElements needs to be called before passing it to Excalidraw Component via initialData, updateScene or any such API.

Live Editor
Result
Loading...

You can pass additional properties as well to decorate the shapes.

info

You can copy the below test examples and replace the elements in the live editor above to test it out.

convertToExcalidrawElements([
{
type: "rectangle",
x: 50,
y: 250,
width: 200,
height: 100,
backgroundColor: "#c0eb75",
strokeWidth: 2,
},
{
type: "ellipse",
x: 300,
y: 250,
width: 200,
height: 100,
backgroundColor: "#ffc9c9",
strokeStyle: "dotted",
fillStyle: "solid",
strokeWidth: 2,
},
{
type: "diamond",
x: 550,
y: 250,
width: 200,
height: 100,
backgroundColor: "#a5d8ff",
strokeColor: "#1971c2",
strokeStyle: "dashed",
fillStyle: "cross-hatch",
strokeWidth: 2,
},
]);

image

Text Element

The type, x, y and text properties are required to create a text element, rest of the attributes are optional

convertToExcalidrawElements([
{
type: "text",
x: 100,
y: 100,
text: "HELLO WORLD!",
},
{
type: "text",
x: 100,
y: 150,
text: "STYLED HELLO WORLD!",
fontSize: 20,
strokeColor: "#5f3dc4",
},
]);

image

Lines and Arrows

The type, x, and y properties are required, rest of the attributes are optional

convertToExcalidrawElements([
{
type: "arrow",
x: 100,
y: 20,
},
{
type: "line",
x: 100,
y: 60,
},
]);

image

With Addtional properties

convertToExcalidrawElements([
{
type: "arrow",
x: 450,
y: 20,
startArrowhead: "circle",
endArrowhead: "triangle",
strokeColor: "#1971c2",
strokeWidth: 2,
},
{
type: "line",
x: 450,
y: 60,
strokeColor: "#2f9e44",
strokeWidth: 2,
strokeStyle: "dotted",
},
]);

image

Text Containers

In addition to type, x and y properties, label property is required for text containers. The text property in label is required, rest of the attributes are optional.

If you don't provide the dimensions of container, we calculate it based of the label dimensions.

convertToExcalidrawElements([
{
type: "rectangle",
x: 300,
y: 290,
label: {
text: "RECTANGLE TEXT CONTAINER",
},
},
{
type: "ellipse",
x: 500,
y: 100,
label: {
text: "ELLIPSE\n TEXT CONTAINER",
},
},
{
type: "diamond",
x: 100,
y: 100,
label: {
text: "DIAMOND\nTEXT CONTAINER",
},
},
]);

image

With Additional properties

convertToExcalidrawElements([
{
type: "diamond",
x: -120,
y: 100,
width: 270,
backgroundColor: "#fff3bf",
strokeWidth: 2,
label: {
text: "STYLED DIAMOND TEXT CONTAINER",
strokeColor: "#099268",
fontSize: 20,
},
},
{
type: "rectangle",
x: 180,
y: 150,
width: 200,
strokeColor: "#c2255c",
label: {
text: "TOP LEFT ALIGNED RECTANGLE TEXT CONTAINER",
textAlign: "left",
verticalAlign: "top",
fontSize: 20,
},
},
{
type: "ellipse",
x: 400,
y: 130,
strokeColor: "#f08c00",
backgroundColor: "#ffec99",
width: 200,
label: {
text: "STYLED ELLIPSE TEXT CONTAINER",
strokeColor: "#c2255c",
},
},
]);

image

Sticky Notes

A sticky note is an always-filled note whose label auto-fits: the font shrinks from the label's fontSize (the note's font ceiling) down to a minimum, and only then does the note grow in height. Only type, x and y are required; width/height default to a 250×250 square and label is optional. The note's strokeColor is its ink — its text and creation-date footer are always one color; a label that sets its own strokeColor gives it to the note. A footer band below the label shows the note's creation date (created); pass created: null for a note without one (the band stays reserved, but empty).

convertToExcalidrawElements([
{
type: "stickynote",
x: 100,
y: 100,
label: {
text: "Remember to ship it",
fontSize: 28,
},
},
{
type: "stickynote",
x: 400,
y: 100,
width: 200,
height: 200,
backgroundColor: "#fcc2d7",
strokeColor: "#c2255c",
},
]);

Notes keep their invariants regardless of the properties you pass: the background is never transparent (it falls back to the default yellow), the fill is solid, and the size is at least 75×75. The height you pass is kept as the note's baseHeight; if a label needs more room at the minimum font size, the created note is taller.

Labelled Arrows

Similar to Text Containers, you can create labelled arrows as well.

convertToExcalidrawElements([
{
type: "arrow",
x: 100,
y: 100,
label: {
text: "LABELED ARROW",
},
},
{
type: "arrow",
x: 100,
y: 200,
label: {
text: "STYLED LABELED ARROW",
strokeColor: "#099268",
fontSize: 20,
},
},
{
type: "arrow",
x: 100,
y: 300,
strokeColor: "#1098ad",
strokeWidth: 2,
label: {
text: "ANOTHER STYLED LABELLED ARROW",
},
},
{
type: "arrow",
x: 100,
y: 400,
strokeColor: "#1098ad",
strokeWidth: 2,
label: {
text: "ANOTHER STYLED LABELLED ARROW",
strokeColor: "#099268",
},
},
]);

image

Arrow bindings

To bind arrow to a shape you need to specify its start and end properties. You need to pass either type or id property in start and end properties, rest of the attributes are optional

convertToExcalidrawElements([
{
type: "arrow",
x: 255,
y: 239,
label: {
text: "HELLO WORLD!!",
},
start: {
type: "rectangle",
},
end: {
type: "ellipse",
},
},
]);

When position for start and end properties are not specified, we compute it according to arrow position.

image

convertToExcalidrawElements([
{
type: "arrow",
x: 255,
y: 239,
label: {
text: "HELLO WORLD!!",
},
start: {
type: "text",
text: "HEYYYYY",
},
end: {
type: "text",
text: "WHATS UP ?",
},
},
]);

image

When passing id

Useful when you want to bind multiple arrows to one diagram / use some existing diagram

convertToExcalidrawElements([
{
type: "ellipse",
id: "ellipse-1",
strokeColor: "#66a80f",
x: 390,
y: 356,
width: 150,
height: 150,
backgroundColor: "#d8f5a2",
},
{
type: "diamond",
id: "diamond-1",
strokeColor: "#9c36b5",
width: 100,
x: -30,
y: 380,
},
{
type: "arrow",
x: 100,
y: 440,
width: 295,
height: 35,
strokeColor: "#1864ab",
start: {
type: "rectangle",
width: 150,
height: 150,
},
end: {
id: "ellipse-1",
},
},
{
type: "arrow",
x: 60,
y: 420,
width: 330,
strokeColor: "#e67700",
start: {
id: "diamond-1",
},
end: {
id: "ellipse-1",
},
},
]);

image

Frames

To create a frame, you need to pass type, children (list of Excalidraw element ids). The rest of the attributes are optional.

{
type: "frame";
children: readonly ExcalidrawElement["id"][];
name?: string;
} & Partial<ExcalidrawFrameElement>);
convertToExcalidrawElements([
{
"type": "rectangle",
"x": 10,
"y": 10,
"strokeWidth": 2,
"id": "1"
},
{
"type": "diamond",
"x": 120,
"y": 20,
"backgroundColor": "#fff3bf",
"strokeWidth": 2,
"label": {
"text": "HELLO EXCALIDRAW",
"strokeColor": "#099268",
"fontSize": 30
},
"id": "2"
},
{
"type": "frame",
"children": ["1", "2"],
"name": "My frame"
}]
}