New to Kendo UI for AngularStart a free 30-day trial

Drawing Shapes

Updated on Sep 18, 2026

The Drawing library provides a set of built-in shape types that you combine to construct a scene. Use them whenever you need to render custom vector graphics programmatically—for example, diagrams, annotations, badges, or any visual that no ready-made component covers.

Every scene follows the same three steps: create shapes, optionally combine them under a Group, and render them on a Surface.

The following example demonstrates the complete implementation for rendering a static scene—a small analytics widget that combines nearly every shape type the library offers: path (the card border, an icon glyph, and a trend line), text, an image, circle elements (an icon badge and a progress-ring track), and an arc (the progress-ring sweep).

Example
View Source
Loading ...

Available Shapes

Choose the shape type that matches what you want to draw:

  • Path—Straight lines, curves, and closed figures. The most flexible primitive; use it for borders, custom outlines, and freeform geometry. Build rectangles quickly with the static Path.fromRect method.
  • MultiPath—A single element that holds several disconnected sub-paths.
  • Circle and Arc—Circular and elliptical shapes and segments.
  • Text—A single line of text with a configurable font and fill.
  • Image—A bitmap image drawn from a URL within a bounding Rect.
  • Group—A container that positions and transforms its children as one unit.

Appearance is controlled through the shared ShapeOptions that every shape accepts in its constructor—for example, stroke, fill, and transform. To position and size shapes, use the geometry helpers such as Point, Rect, and Size.

Importing the Types

Import the shape and surface elements you need directly from @progress/kendo-drawing. Geometry helpers, such as Point, Rect, and Size, are exposed through the geometry namespace, so destructure them from it instead of importing them by name.

ts
import { geometry, Arc, Circle, Group, Image, Path, Surface, Text } from "@progress/kendo-drawing";
const { Point, Rect, Size, transform } = geometry;

geometry also exposes a Circle and an Arc type that describe a circle's center and radius and an arc's angular sweep. Because those names collide with the Circle and Arc shape elements imported above, keep them namespaced—reference them as geometry.Circle and geometry.Arc instead of destructuring, as shown in Drawing the Circle.

Drawing the Path

To draw straight lines, curves, or a combination of both, use the Path element. The example uses Path for three different purposes: the card border, a small trend-arrow icon, and a sparkline chart.

  1. Set the stroke (line) color and width to match the picture. The constructor accepts the ShapeOptions object that controls the appearance of the shape.

    ts
    const border = new Path({
        stroke: {
            color: "#e2e4ea",
            width: 1.5,
        },
    });
  2. Set the initial position of the line by using the moveTo command. To draw the four sides, use the lineTo command. The last close command closes the path and draws a straight line to the initial position.

    ts
    border.moveTo(0, 0).lineTo(380, 0).lineTo(380, 210).lineTo(0, 210).close();

    Alternatively, you can also use the static fromRect method because the figure from the example is a rectangle.

    ts
    const borderRect = new Rect(new Point(0, 0), new Size(380, 210));
    const border = Path.fromRect(borderRect, {
        stroke: {
            color: "#e2e4ea",
            width: 1.5,
        },
    });
  3. Reuse the same Path API for a simple icon glyph and a data line—moveTo/lineTo chains are not limited to closed shapes.

    ts
    const iconArrow = new Path({
        stroke: { color: "#ffffff", width: 2.5, lineCap: "round", lineJoin: "round" },
    }).moveTo(48, 54).lineTo(56, 42).lineTo(64, 54);
    
    const sparkline = new Path({
        stroke: { color: "#2563eb", width: 2, lineCap: "round", lineJoin: "round" },
    }).moveTo(56, 152).lineTo(112, 160).lineTo(168, 138).lineTo(224, 146).lineTo(280, 118).lineTo(336, 108);

Drawing the Image

To draw an image, use the Image element which draws a bitmap image from a given URL.

  1. Define the position and size of the image as a Rect element.

    ts
    const photoRect = new Rect(new Point(30, 168), new Size(28, 28));
  2. (Optional) Shorten the previous code statement.

    Each method that expects Point and Size also accepts [x, y] and [width, height] arrays.

    ts
    const photoRect = new Rect([30, 168], [28, 28]);
  3. Create the image.

    ts
    const photo = new Image("../assets/diego.jpg", photoRect);

Drawing the Text

To draw the text, use the Text element which draws a single line of text. Appearance options, such as the font and fill color, are set through ShapeOptions. The Point configuration defines the position of the top-left corner. Add more Text elements at different positions to lay out labels, values, and captions.

ts
const label = new Text("MONTHLY REVENUE", new Point(90, 36), { font: "10px Arial", fill: { color: "#6b7280" } });
const value = new Text("$48,250", new Point(90, 44), { font: "bold 26px Arial", fill: { color: "#111827" } });
const trend = new Text("\u2191 12.4% vs last month", new Point(90, 84), { font: "12px Arial", fill: { color: "#16a34a" } });

Drawing the Circle

To draw circles, such as an icon badge, use the Circle element, which accepts a geometry.Circle (center and radius) and the usual ShapeOptions.

ts
const iconBadge = new Circle(new geometry.Circle([56, 50], 20), { fill: { color: "#2563eb" } });

Combine a Circle with an Arc to build a progress ring—the circle draws the full "track," and the arc, which accepts a geometry.Arc describing the center, radius, and angular sweep, draws the colored progress on top of it.

ts
const ringTrack = new Circle(new geometry.Circle([330, 58], 30), { stroke: { color: "#e5e7eb", width: 6 } });
const ringProgress = new Arc(new geometry.Arc([330, 58], { startAngle: -90, endAngle: 183.6, radiusX: 30, radiusY: 30 }), {
    stroke: { color: "#2563eb", width: 6, lineCap: "round" },
});

Drawing the Gradient

To add a gradient color to the background, use the Gradient and LinearGradient classes.

Example
View Source
Loading ...

Grouping the Shapes

It is convenient to treat a group of shapes as a single entity. To set the position of all elements at once, use the group constructor.

  1. Create a Group element.

    ts
    const ringLabel = new Text("72%", new Point(315, 62), {
        font: "bold 14px Arial",
        fill: { color: "#111827" },
    });
    
    const ringCaption = new Text("Goal", new Point(316, 82), {
        font: "10px Arial",
        fill: { color: "#6b7280" },
    });
  2. Append the created shapes to the group.

    ts
    const group = new Group();
    group.append(ringLabel, ringCaption);
  3. Set the transformation which applies to all group children—to effectively make the coordinates of the element relative, translate their parent group.

    ts
    group.transform(transform().translate(30, 30));

Creating the Surface

To create the surface, use the Surface.create method which chooses an implementation that matches the capabilities of the browser. The default output is an SVG with a fallback to Canvas.

The following example demonstrates how to apply Surface.create. The surface is created in the AppComponent.

ts
// Obtain a reference to the native DOM element of the wrapper
const element = this.surfaceElement.nativeElement;

// Create a drawing surface
this.surface = Surface.create(element);

Rendering the Scene

To render the scene, use the draw method of the surface which appends shapes to the scene graph.

ts
surface.draw(group);

Attaching Events to Surface Elements

To attach events to the Surface, use the bind method which accepts the event name and a handler function.

ts
surface.bind("click", (args: SurfaceEvent) => {
    console.log("Click event", args);
});

The following example demonstrates how to attach a click event to the surface and change the color of the clicked element.

Example
View Source
Loading ...