# 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](https://github.com/excalidraw/excalidraw/pull/6546) for more details. For this purpose we introduced a new type [`ExcalidrawElementSkeleton`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L133). This is the simplified version of [`ExcalidrawElement`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L134) 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`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L133) can be converted to fully qualified Excalidraw elements by using [`convertToExcalidrawElements`](/docs/@excalidraw/excalidraw/api/excalidraw-element-skeleton#converttoexcalidrawelements). ## convertToExcalidrawElements **_Signature_** ```ts convertToExcalidrawElements( elements: ExcalidrawElementSkeleton, opts?: { regenerateIds: boolean } ): ExcalidrawElement[] ``` | Name | Type | Default | Description | | --- | --- | --- | --- | | `elements` | [ExcalidrawElementSkeleton](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L137) | | 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_** ```js 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`](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props/initialdata), [`updateScene`](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props/excalidraw-api#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. ```jsx live function App() { const elements = convertToExcalidrawElements([ { type: "rectangle", x: 100, y: 250, }, { type: "ellipse", x: 250, y: 250, }, { type: "diamond", x: 380, y: 250, }, ]); return (
); } ``` You can pass additional [`properties`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/element/types.ts#L27) 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. ::: ```js 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](https://github.com/excalidraw/excalidraw/assets/11256141/70ca7063-88fb-434c-838a-cd466e1bc3c2) ### Text Element The `type`, `x`, `y` and `text` properties are required to create a text element, rest of the attributes are optional ```js 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](https://github.com/excalidraw/excalidraw/assets/11256141/085c7ac3-7952-4f22-b9c3-6beb51438526) ### Lines and Arrows The `type`, `x`, and `y` properties are required, rest of the attributes are optional ```js convertToExcalidrawElements([ { type: "arrow", x: 100, y: 20, }, { type: "line", x: 100, y: 60, }, ]); ``` ![image](https://github.com/excalidraw/excalidraw/assets/11256141/0c22a06b-b568-4ab5-9848-a5f0160f66a6) #### With Addtional properties ```js 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](https://github.com/excalidraw/excalidraw/assets/11256141/14f1bf3f-ad81-4096-8c1c-f35235084ec5) ### Text Containers In addition to `type`, `x` and `y` properties, [`label`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L124C7-L130C59) 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. ```js 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](https://github.com/excalidraw/excalidraw/assets/11256141/1e2c7b5d-fcb4-4f86-946d-0bfb0e97d532) #### With Additional properties ```js 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](https://github.com/excalidraw/excalidraw/assets/11256141/f8123cd1-c9aa-452d-b96b-05c846c5030d) ### Labelled Arrows Similar to Text Containers, you can create labelled arrows as well. ```js 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](https://github.com/excalidraw/excalidraw/assets/11256141/70635e9b-f1c8-4839-89e1-73b813abeb93) ### Arrow bindings To bind arrow to a shape you need to specify its [`start`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L86) and [`end`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/transform.ts#L54) properties. You need to pass either `type` or `id` property in `start` and `end` properties, rest of the attributes are optional ```js 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](https://github.com/excalidraw/excalidraw/assets/11256141/5aff09fd-b7e8-4c63-98be-da40b0698704) ```js convertToExcalidrawElements([ { type: "arrow", x: 255, y: 239, label: { text: "HELLO WORLD!!", }, start: { type: "text", text: "HEYYYYY", }, end: { type: "text", text: "WHATS UP ?", }, }, ]); ``` ![image](https://github.com/excalidraw/excalidraw/assets/11256141/2a9f03ac-e45c-4fbd-9be0-5d9f8c8e0343) #### When passing `id` Useful when you want to bind multiple arrows to one diagram / use some existing diagram ```js 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](https://github.com/excalidraw/excalidraw/assets/11256141/a8b047c8-2eed-4aea-82a2-e1e6bbddb8d4) ### Frames To create a frame, you need to pass `type`, `children` (list of Excalidraw element ids). The rest of the attributes are optional. ```ts { type: "frame"; children: readonly ExcalidrawElement["id"][]; name?: string; } & Partial); ``` ```ts 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" }] } ```