Drawing Shapes
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).
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 staticPath.fromRectmethod.MultiPath—A single element that holds several disconnected sub-paths.CircleandArc—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 boundingRect.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.
import { geometry, Arc, Circle, Group, Image, Path, Surface, Text } from "@progress/kendo-drawing";
const { Point, Rect, Size, transform } = geometry;
geometryalso exposes aCircleand anArctype that describe a circle's center and radius and an arc's angular sweep. Because those names collide with theCircleandArcshape elements imported above, keep them namespaced—reference them asgeometry.Circleandgeometry.Arcinstead 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.
-
Set the stroke (line) color and width to match the picture. The constructor accepts the
ShapeOptionsobject that controls the appearance of the shape.tsconst border = new Path({ stroke: { color: "#e2e4ea", width: 1.5, }, }); -
Set the initial position of the line by using the
moveTocommand. To draw the four sides, use thelineTocommand. The lastclosecommand closes the path and draws a straight line to the initial position.tsborder.moveTo(0, 0).lineTo(380, 0).lineTo(380, 210).lineTo(0, 210).close();Alternatively, you can also use the static
fromRectmethod because the figure from the example is a rectangle.tsconst borderRect = new Rect(new Point(0, 0), new Size(380, 210)); const border = Path.fromRect(borderRect, { stroke: { color: "#e2e4ea", width: 1.5, }, }); -
Reuse the same
PathAPI for a simple icon glyph and a data line—moveTo/lineTochains are not limited to closed shapes.tsconst 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.
-
Define the position and size of the image as a
Rectelement.tsconst photoRect = new Rect(new Point(30, 168), new Size(28, 28)); -
(Optional) Shorten the previous code statement.
Each method that expects
PointandSizealso accepts[x, y]and[width, height]arrays.tsconst photoRect = new Rect([30, 168], [28, 28]); -
Create the image.
tsconst 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.
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.
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.
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.
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.
-
Create a
Groupelement.tsconst 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" }, }); -
Append the created shapes to the group.
tsconst group = new Group(); group.append(ringLabel, ringCaption); -
Set the transformation which applies to all group children—to effectively make the coordinates of the element relative, translate their parent group.
tsgroup.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.
// 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.
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.
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.