library(minixcali) library(purrr) library(knitr) opts_chunk$set(message = FALSE, warning=FALSE, fig.width = 7, fig.height = 3, out.width='100%') knitr::include_graphics('overview.png')
Excalidraw can import and export its scenes in json; the format consists of 5 top-level entries, of which the important one is elements
, which is an array containing the description of each basic glyph in the scene.
{ "type": "excalidraw", "version": 2, "source": "https://excalidraw.com", "elements": [ { "type": "rectangle", "fillStyle": "solid", [...] "groupIds": [] }, { "type": "rectangle", "fillStyle": "solid", [...] "groupIds": [] } ], "appState": { "viewBackgroundColor": "#ffffff", "gridSize": null } }
Note that there doesn't appear to be a device size / viewport / viewbox. I'm also unsure what the units are; looking at the SVG export it seems to be the same default "px", i.e. 1/96th of an inch, i.e. about a quarter of a mm.
Most attributes are pretty straight-forward,
The following are for text (but it doesn't seem to hurt if irrelevant parameters are passed to another shape type),
Each glyph is assigned some identification,
Finally the following attributes for collaboration,
minixcali
defines a very basic R6 class ExcaliDocument
which initialises the 5 top-level nodes of the json object. Two methods are defined,
$add
, to add glyphs to the elements
field$export
, to save the object to a json file (via jsonlite
)The $add
method simply appends glyph(s) to the list of elements. Each glyph needs to be a well-formed list of attributes, such as
list(type = "rectangle", x = -407.242554, y = 0, width = 44, height = 44, angle = 0, strokeColor = "#495057", backgroundColor = "#ced4da", fillStyle = "hachure", strokeWidth = 1, strokeStyle = "solid", roughness = 1L, opacity = 100L, strokeSharpness = "sharp", isDeleted = FALSE, groupIds = list(), boundElementIds = NA, id = "2732dc14872d3709d5978813d7bf550c", seed = 1260353516L, version = 32L, versionNonce = 784119031L)
minixcali
provides 4 functions (xkd_rectangle()
, xkd_ellipse()
, xkd_draw()
, xkd_text()
) to generate such lists from the set of default parameters.
str(xkd_text(text = "new label", strokeColor = "#555555"))
To create multiple shapes at once it can be useful to create a list or data.frame of attributes, and use purrr
functions to iterate over them,
a <- tibble::tribble(~x, ~y, ~width, ~height, ~roughness, ~backgroundColor, -300 , -80, 300, 300, 0, "#ced4da", 10 , -80, 300, 300, 1, "#ced4da", 320 , -80, 300, 300, 2, "#ced4da") a$strokeWidth <- 2 d <- Excali_doc() invoke(d$add, pmap(a, xkd_rectangle)) str(d$elements, max.level = 1)
We can the export the full tree to json and open it in Excalidraw,
d$export(file='testing.json') knitr::include_graphics('testing.png')
The drawing may be edited at https://excalidraw.com/#json=5181621544157184,h3q8WL5-2HPBFjkjQeu5RA
line
, arrow
and draw
elements (the difference is in the interaction with online tools; there's none from the JSON perspective) require a points
attribute that encodes (x,y) node coordinates in an array structure.
Say we have inherited some (x,y) coordinates representing a polygon from a drawing program; we can insert them into the points
attribute and from there generate the scene as above. It is also possible to group multiple paths by giving them a common group
attribute, as illustrated below. The resulting group can then be edited (moved, rotated, attribute changes, etc.) as one object in Excalidraw.
source(system.file("samples/pdl.R", package = "minixcali")) str(.kevin) # stored coords in the package under data/ d <- Excali_doc() for (l in .kevin) { call <- c(l, list( groupIds = list(list("kevin")), strokeSharpness = "round", fillStyle = "solid", strokeWidth = 1L, roughness = 0L ) ) shape <- invoke(xkd_draw, call) d$add(shape) } d$export('drawing.json')
Drawing at https://excalidraw.com/#json=5903088405708800,72BcP2Ry6NHWbHEUpidg9w
knitr::include_graphics('kevin.png')
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.