Shapes

A drawing is composed of shapes. Shapes are added either by tools or by you, programmatically. All shapes are created through the LC.createShape() function.

A “color” is a CSS color string.

Creating shapes

Note

This section might be out of date. Read the source.

LC.createShape('Image', {x, y, image})
Arguments:
  • x/y – Upper left corner position
  • scale – Scale of the image. Defaults to 1.0.
  • image – A DOM Image object

Note

If you’d like to add an image.onload callback, do not assign it directly! This will break several things. Instead, use LC.util.addImageOnload().

LC.createShape('Rectangle', {x, y, width, height, strokeWidth, strokeColor, fillColor})
Arguments:
  • x/y – Upper left corner position
  • width/height – Size of the rectangle
  • strokeWidth – Width of the border
  • strokeColor – Color of the border
  • fillColor – Color of the middle
LC.createShape('Line', {x1, y1, x2, y2, strokeWidth, color, capStyle, endCapShapes})
Arguments:
  • x1/y1 – One end of the line
  • x2/y2 – Other end of the line
  • strokeWidth – Width of the line
  • color – Color of the line
  • capStyle – Line cap style. Defaults to 'round'. Read the HTML <canvas> docs for other valid values.
  • endCapShapes – Two-item list [srcShapeId, destShapeId], where each value is 'arrow' or null.
  • dash – Value to be passed to ctx.setLineDash() when this line is rendered.
LC.createShape('Text', {x, y, text, color, font})
Arguments:
  • x/y – Top left corner position
  • text – String to render
  • color – Text color
  • font – Font settings string. The format is apprimately "[italic] [bold] fontSize fontName".
  • forcedWidth – If null, this shape’s width is equal to the rendered width of the text. Otherwise, the text is wrapped to this width.
  • forcedHeight – Height the user has specified for this text box. Ignored when rendering; only used to show the dragging box while resizing.
  • v – Version of the text shape API this shape was created with. Defaults to 1. Shapes from version 0 will be converted to version 1.
LC.createShape('LinePath', {points, smooth})
Arguments:
  • points – List of Point objects
  • smooth – If true, the given points will be smoothed to look more natural. Defaults to true.
LC.createShape('ErasedLinePath', {points, interpolate})
Arguments:
  • points – List of Point objects
  • smooth – If true, the given points will be smoothed to look more natural. Defaults to true.
LC.createShape('Polygon', {points, fillColor, strokeColor, strokeWidth, isClosed})
Arguments:
  • points – List of Point objects
  • fillColor – Fill color
  • strokeColor – Stroke color
  • strokeWidth – Width of the line around the edge.
  • isClosed – If true, draws a line between the first and last points.
LC.createShape('Ellipse', {x, y, width, height, strokeWidth, strokeColor, fillColor})
Arguments:
  • points – List of Point objects
  • fillColor – Fill color
  • strokeColor – Stroke color
  • strokeWidth – Width of the line around the edge.
LC.createShape('Point', {x, y, size, color})
Arguments:
  • x/y – Upper left corner position
  • size – Size of the rectangle
  • color – Color of the point

Point is primarily an internal data structure for LinePath and ErasedLinePath. It can’t currently be drawn.

LC.createShape('SelectionBox', {shape, backgroundColor})

Note

This shape is mostly for internal use.

Arguments:
  • shape – Shape to draw the box around
  • backgroundColor – Color to render behind the selection box

Shapes and JSON

Each shape has a JSON representation so that you can save and load drawings. But just calling shape.toJSON() won’t give you a value that you can decode later; Literally Canvas wraps these values in containers with additional information. Instead, you can use these functions to save and load shapes:

LC.shapeToJSON(shape)
Returns:JSON-encoded string representing shape
LC.JSONToShape(jsonEncodedString)
Returns:Shape instance constructed from jsonEncodedString

If you’ve saved a snapshot with LC.getSnapshot() or LC.getSnapshotJSON(), you can convert that to a list of deserialized shape objects with these functions:

LC.snapshotToShapes(snapshot)
LC.snapshotJSONToShapes(snapshotJSON)

Rendering shapes outside of an interactive session

LC.renderShapesToCanvas(shapes, bounds, scale=1, canvas=null)

Draws the given shapes to the given canvas. Creates a new canvas if none is provided. Returns the canvas containing the rendered shapes.

Arguments:
  • shapes – List of shapes
  • bounds – A dict {x, y, width, height} specifying which part of the image to draw, in drawing coordinates (before scaling).
  • scale – Amount by which to scale the image output. Shapes will be rendered at full resolution. Defaults to 1.
  • canvas – Canvas object on which to render the shapes. If null, a new canvas will be created with the size specified by bounds.

This function can be used to render a snapshot to an image without instantiating a LiterallyCanvas() object like this:

var snapshotJSON = localStorage['saved-snapshot'];
var canvas = LC.renderShapesToCanvas(
  LC.snapshotJSONToShapes(snapshotJSON),
  {x: 0, y: 0, width: 100, height: 100});
// Now you can pull out the image using a data URL:
var dataURL = canvas.toDataURL();
// Or pull out the bytes using the canvas API.
LC.renderShapesToSVG(shapes, bounds, backgroundColor)

Converts the list of shapes to an SVG string.

Arguments:
  • shapes – List of shapes
  • bounds – A dict {x, y, width, height} specifying which part of the image to draw, in drawing coordinates.
  • backgroundColor – SVG color to draw behind the shapes.

This function can be used to render a snapshot to SVG without instantiating a LiterallyCanvas() object like this:

var snapshotJSON = localStorage['saved-snapshot'];
var svgString = LC.renderShapesToSVG(
  LC.snapshotJSONToShapes(snapshotJSON),
  {x: 0, y: 0, width: 100, height: 100},
  'transparent');

Defining shapes

If you want to make your own tool, or do some custom canvas rendering as the background of your drawing, you’ll need to define a shape. Then you can create it using the LC.createShape() function.

LC.defineShape(name, methods)
LC.defineCanvasRenderer(name, drawShape)
Arguments:
  • name – Name of the shape
  • drawShape – A function that takes (canvasContext, shape) and renders the shape to the context.
LC.defineSVGRenderer(name, shapeToSVGString)
Arguments:
  • name – Name of the shape
  • shapeToSVGString – A function that returns an SVG string representing the given shape.
LC.defineShape('MyAwesomeShape', {
  /* initialize using the args passed to LC.createShape() */
  constructor: function(args) {
    this.x = args.x;
    this.y = args.y;
    this.doStuff();
  },

  /* you can add arbitrary methods */
  doStuff: function() {},

  /* provide a bounding rectangle so getImage() can figure out the image
     bounds (semi-optional) */
  getBoundingRect: function() {
    return {x: this.x, y: this.y, width: 0, height: 0};
  },

  /* return a dictionary representation of the shape from which this instance
     can be reconstructed */
  toJSON: function() {
    return {x: this.x, y: this.y};
  },

  /* reconstruct the MyAwesomeShape from the representation given by
     toJSON */
  fromJSON: function(data) {
    return LC.createShape('MyAwesomeShape', data);
  }
});

/* Define canvas and SVG renderers */

LC.defineCanvasRenderer('MyAwesomeShape', function(ctx, shape) {
  ctx.renderStuff();
})

// You can skip this step if you never export to SVG
LC.defineSVGRenderer('MyAwesomeShape', function(shape) {
  return "<BestShapeEver />";
})

/* you can use it as a background */
var lc = LC.init(element, {
  backgroundShapes: [LC.createShape('MyAwesomeShape', {x: 0, y: 0})]
});

/* you can add it as part of the drawing */
lc.saveShape(LC.createShape('MyAwesomeShape', {x: 100, y: 100}))

Adding shapes to drawings programmatically

You can add a shape to the drawing with the LiterallyCanvas.saveShape() method, like this:

// let's put a kitten in our drawing
var lc = LC.init(element, options);
var img = new Image();
img.src = 'http://placekitten.com/200/300';
lc.saveShape(LC.createShape('Image', {x: 100, y: 100, image: img}))