Creating shapes
Shapes are fundamental elements that users can add to their Canva designs. There are a number of shapes built into Canva, such as circles and rectangles, and apps can create their own shapes.
Why create shapes?
- Shapes can be resized without becoming blurry.
- Shapes are faster to create than equivalent images.
- Shapes don't count against a user's upload quota.
The user experience
After an app adds a shape to a user's design, the shape is indistinguishable from Canva's built-in shapes. This means the user can manipulate the shape in all the same ways, including:
- Moving, resizing, and rotating the shape
- Adjusting the color(s) of the shapes
The anatomy of shapes
Shapes are comparable to Scalable Vector Graphics (SVGs), in that they're made up of paths, fills, strokes, and a view box. There are, however, some nuances that distinguish them from SVGs.
Paths
A path is a combination of one or more lines that forms a shape. For example, a path could be a single line that forms a circle or a combination of lines that forms a hexagon.
By themselves, paths are not visible. They define the boundaries of a shape but not the contents of a shape. For a path to be made visible, it requires a fill or a stroke.
Using path commands
A path command defines the position, length, and curvature of a path.
Path commands are made up of two ingredients:
- A letter that defines what the path command does
- A list of numeric parameters
For example, the following path commands draw a square:
M 0 0H 100V 100H 0L 0 0
Here's a breakdown of what these commands are doing:
M 0 0moves the current point to0on the X axis and0on the Y axis.H 100draws a line to100on the X axis and0on the Y axis.V 100draws a line to100on the X axis and100on the Y axis.H 0draws a line to0on the X axis and100on the Y axis.L 0 0draws a line to0on the X axis and0on the Y axis.
Supported path commands
When creating shapes, the following path commands are available:
- MoveTo: M, m
- LineTo: L, l, H, h, V, v
- Cubic Bézier Curve: C, c, S, s
- Elliptical Arc Curve: A, a
- ClosePath: Z, z
A command that is available to SVGs but is not available to shapes is the Q command, which is used to create quadratic Bézier curves.
How casing affects path commands
Path commands are case sensitive and their behavior depends on their casing.
When a command is uppercase, the parameters are absolute coordinates — that is, relative to an origin of 0,0. When a command is lowercase, the parameters are relative to the previous coordinate.
Path limitations
- A shape must have between 1 and 30 paths.
- The maximum combined size of all paths must not exceed 2kb.
- Paths must start with an
Mcommand. - Paths must not have more than one
Mcommand. - Paths must not use the
Qcommand. - Paths must be closed in either of the following ways:
- With a
Zcommand at the end - By having the last coordinate match the first coordinate
- With a
Fills
A fill defines the interior of a path. It can be a color, an image, or a video. For example, if you wanted to create a pink square, the color pink would be the fill.
It's also worth noting that:
- The maximum number of unique fill colors across a shape's paths must not exceed 6.
- If a fill is a drop target and doesn't have a color, image, or a video, it will be a frame.
- If a fill is not a drop target and doesn't have a color, image, or a video, it will be transparent.
Strokes
A stroke is an outline that can be applied to a path. This outline is rendered along the edges of a path and can be configured with a custom weight (width) and color.
View box
The view box is a rectangular area that defines the coordinates of the shape. It determines how the shape should be scaled, rotated, or positioned when it's displayed.
To learn more, see the MDN documentation(opens in a new tab or window).
How to create shapes
Step 1: Enable the required scopes
In the Developer Portal, enable the canva:design:content:write scope. In the future, the Apps SDK will throw an error if the required scopes aren't enabled. To learn more, see Configuring scopes.
Step 2: Add to the shape to the design
Import the addElementAtPoint method (or addElementAtCursor, depending on the current context) from the @canva/design package:
import { addElementAtPoint } from "@canva/design";
Call the method, passing in the structure of a shape as the only argument. The following code sample demonstrates how to create a pink square with the minimum required properties:
await addElementAtPoint({type: "shape",paths: [{d: "M 0 0 H 100 V 100 H 0 L 0 0",fill: {color: "#ff0099",},},],viewBox: {height: 100,width: 100,left: 0,top: 0,},});
You can create more complex shapes by adding additional, more complex paths.
How to create drop targets
The fill of a shape can be defined as a drop target. When a fill is a drop target, users can update a fill by dragging and dropping an image or video onto it.
To define a fill as a drop target:
-
Import the
addElementAtPointmethod (oraddElementAtCursor, depending on the current context) from the@canva/designpackage:import { addElementAtPoint } from "@canva/design";TS -
When creating a fill, set the
dropTargetproperty totrue:await addElementAtPoint({type: "shape",paths: [{d: "M 0 0 H 100 V 100 H 0 L 0 0",fill: {dropTarget: true,color: "#ff0099",},},],viewBox: {height: 100,width: 100,left: 0,top: 0,},});TS
When importing addElementAtPoint from @canva/design, be aware that:
- The
dropTargetproperty is optional for all fills, but we encourage you to include it and set tofalsein case of any future API changes.
How to use image and video fills
The fill of a shape can be a color, image, or video.
To set the fill to an image or video:
-
Import the
addElementAtPointmethod (oraddElementAtCursor, depending on the current context) from the@canva/designpackage:import { addElementAtPoint } from "@canva/design";TS -
Import the
uploadmethod from the@canva/assetpackage:import { upload } from "@canva/asset";TS -
Upload an image or video to Canva's backend:
const image = await upload({type: "image",mimeType: "image/jpeg",url: "https://www.canva.dev/example-assets/image-import/image.jpg",thumbnailUrl: "https://www.canva.dev/example-assets/image-import/thumbnail.jpg",aiDisclosure: "none"});TSThe
uploadmethod returns arefproperty. This property contains a unique identifier that points to an asset in Canva's backend. To learn more, see Assets. -
Pass the
refproperty into the fill:await addElementAtPoint({type: "shape",paths: [{d: "M 0 0 H 100 V 100 H 0 L 0 0",fill: {dropTarget: false,asset: {type: "image",ref: image.ref,},},},],viewBox: {height: 100,width: 100,left: 0,top: 0,},});TSAlthough the
dropTargetproperty is optional, we encourage you to set it to prevent breaking in potential future API changes. For image fillsdropTargetcan befalse, but for video fills it must betrue.
API reference
Code sample
import React from "react";import { addElementAtPoint } from "@canva/design";export function App() {async function handleClick() {// Add the shape to the designawait addElementAtPoint({type: "shape",paths: [{d: "M 0 0 H 100 V 100 H 0 L 0 0",fill: {color: "#ff0099",},},],viewBox: {height: 100,width: 100,left: 0,top: 0,},});}return (<div><button onClick={handleClick}>Add shape to design</button></div>);}