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 0
moves the current point to0
on the X axis and0
on the Y axis.H 100
draws a line to100
on the X axis and0
on the Y axis.V 100
draws a line to100
on the X axis and100
on the Y axis.H 0
draws a line to0
on the X axis and100
on the Y axis.L 0 0
draws a line to0
on the X axis and0
on 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
M
command. - Paths must not have more than one
M
command. - Paths must not use the
Q
command. - Paths must be closed in either of the following ways:
- With a
Z
command 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.
How to create shapes
Step 1: Enable the required permissions
In the Developer Portal, enable the canva:design:content:write
permission. In the future, the Apps SDK will throw an error if the required permissions are not enabled. To learn more, see Configuring permissions.
Step 2: Add to the shape to the design
Import the addNativeElement
method from the @canva/design
package:
import { addNativeElement } 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 addNativeElement({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
addNativeElement
method from the@canva/design
package:import { addNativeElement } from "@canva/design";ts -
When creating a fill, set the
dropTarget
property totrue
:await addNativeElement({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 addNativeElement
from @canva/design
, be aware that:
- The
dropTarget
property is optional for all fills, but we encourage you to include it and set tofalse
in 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
addNativeElement
method from the@canva/design
package:import { addNativeElement } from "@canva/design";ts -
Import the
upload
method from the@canva/asset
package: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",});tsThe
upload
method returns aref
property. This property contains a unique identifier that points to an asset in Canva's backend. To learn more, see Uploading assets. -
Pass the
ref
property into the fill:await addNativeElement({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,},});ts
API reference
Code sample
import React from "react";import { addNativeElement } from "@canva/design";export function App() {async function handleClick() {// Add the shape to the designawait addNativeElement({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>);}