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[]
| Name | Type | Default | Description |
|---|---|---|---|
elements | ExcalidrawElementSkeleton | The 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.
You can pass additional properties as well to decorate the shapes.
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,
},
]);
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",
},
]);
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,
},
]);
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",
},
]);
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",
},
},
]);
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",
},
},
]);
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",
},
},
]);
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.
convertToExcalidrawElements([
{
type: "arrow",
x: 255,
y: 239,
label: {
text: "HELLO WORLD!!",
},
start: {
type: "text",
text: "HEYYYYY",
},
end: {
type: "text",
text: "WHATS UP ?",
},
},
]);
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",
},
},
]);
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"
}]
}