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: "dot",
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

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"
}]
}