Practical Guide to Custom Graphics with Canvas in HarmonyOS Next
HarmonyOS Next provides a Canvas component for custom graphics rendering, allowing developers to draw shapes, text, and images using CanvasRenderingContext2D and OffscreenCanvasRenderingContext2D objects.
HarmonyOS Next supports three approaches for custom graphics rendering on Canvas:
-
Direct Drawing on Canvas using
CanvasRenderingContext2D
. - Offscreen Rendering (pre-rendering content in a buffer and converting it into an image for faster drawing).
- Loading Lottie Animations on Canvas.
1. Canvas Drawing Steps
To begin drawing, we must first create a RenderingContextSettings
object, which configures parameters such as anti-aliasing, and then initialize CanvasRenderingContext2D
.
Basic Example
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
build() {
RelativeContainer() {
Canvas(this.context)
.width('100%')
.height('100%')
.backgroundColor('#660099')
}
}
This example sets a background color. The settings
object configures CanvasRenderingContext2D
, including anti-aliasing (true
enables it).
Key Notes:
- Drawing operations must wait for the
onReady
callback, which ensures the Canvas is fully initialized and provides its dimensions. -
onReady(event: () => void)
is triggered when the Canvas is ready, allowing access to its width and height for precise drawing.
2. Offscreen Rendering
Offscreen rendering improves performance by first drawing content in a buffer (OffscreenCanvas
) and then transferring it to the main Canvas as an image.
Process:
- Use
transferToImageBitmap()
to convert the offscreen Canvas into anImageBitmap
. - Use
transferFromImageBitmap()
to display theImageBitmap
on the main Canvas.
Example:
@Entry
@Component
struct Index {
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
private offCanvas: OffscreenCanvas = new OffscreenCanvas(600, 600);
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Canvas(this.context)
.width('100%')
.height('100%')
.backgroundColor('#5F3CE2')
.onReady(() => {
let offContext = this.offCanvas.getContext("2d", this.settings);
offContext.strokeRect(20, 20, 100, 100); // Draw a rectangle offscreen
let image = this.offCanvas.transferToImageBitmap(); // Convert to ImageBitmap
this.context.transferFromImageBitmap(image); // Display on main Canvas
})
}
.width('100%')
.height('100%')
}
}
Steps:
- Create
RenderingContextSettings
(enabling anti-aliasing). - Initialize
OffscreenCanvas
with a specified width and height. - In
onReady
, get the offscreen context (getContext("2d", settings)
). - Draw shapes (e.g.,
strokeRect
) on the offscreen Canvas. - Convert the offscreen rendering to an
ImageBitmap
and transfer it to the main Canvas.
3. Drawing Basic Shapes
(1) Drawing Lines
Use beginPath()
, moveTo()
, and lineTo()
to draw lines.
@Entry
@Component
struct Index {
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Canvas(this.context)
.width('100%')
.height('100%')
.backgroundColor('#cbbbf2')
.onReady(() => {
this.context.beginPath();
this.context.moveTo(150, 50);
this.context.lineTo(200, 150);
this.context.stroke();
})
}
.width('100%')
.height('100%')
}
}
(2) Drawing Rectangles
-
fillRect()
for solid rectangles. -
strokeRect()
for outlined rectangles.
Example (Solid Rectangle):
@Entry
@Component
struct Index {
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Canvas(this.context)
.width('100%')
.height('100%')
.backgroundColor('#cbbbf2')
.onReady(() => {
this.context.fillStyle = '#0097D4';
this.context.fillRect(50, 50, 100, 100);
})
}
.width('100%')
.height('100%')
}
}
(3) Drawing Circles
Use arc()
to draw circles.
@Entry
@Component
struct Index {
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Canvas(this.context)
.width('100%')
.height('100%')
.backgroundColor('#cbbbf2')
.onReady(() => {
let region = new Path2D();
region.arc(100, 75, 50, 0, 6.28); // (x, y, radius, startAngle, endAngle)
this.context.stroke(region);
})
}
.width('100%')
.height('100%')
}
}
(4) Drawing Ellipses
Use ellipse()
for elliptical shapes.
@Entry
@Component
struct Index {
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Canvas(this.context)
.width('100%')
.height('100%')
.backgroundColor('#cbbbf2')
.onReady(() => {
this.context.beginPath();
this.context.ellipse(150, 150, 50, 100, Math.PI * 0.25, Math.PI * 0, Math.PI * 2);
this.context.stroke();
})
}
.width('100%')
.height('100%')
}
}
(5) Text Rendering
Use fillText()
(filled text) and strokeText()
(outlined text).
@Entry
@Component
struct Index {
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Canvas(this.context)
.width('100%')
.height('100%')
.backgroundColor('#cbbbf2')
.onReady(() => {
// Filled text
this.context.font = '50px bolder sans-serif';
this.context.fillText("HarmonyOS!", 50, 100);
// Outlined text
this.context.strokeStyle = "#ff0000";
this.context.lineWidth = 2;
this.context.font = '50px bolder sans-serif';
this.context.strokeText("HarmonyOS", 50, 150);
})
}
.width('100%')
.height('100%')
}
}
4. Additional Features
- Image Drawing: Load and render images on Canvas.
- Pixel Manipulation: Process image pixel data.
-
Gradients: Use
createLinearGradient()
andcreateRadialGradient()
for smooth color transitions.
5. Summary
This guide explored custom graphics rendering in HarmonyOS Next using Canvas, covering:
-
Direct Drawing with
CanvasRenderingContext2D
. - Offscreen Rendering for performance optimization.
- Lottie Animation Support (not covered in detail here).
Key takeaways:
-
onReady
is crucial for ensuring Canvas dimensions are available before drawing. - Offscreen rendering improves efficiency by reducing redraw operations.
- Shape drawing (lines, rectangles, circles, ellipses) and text rendering are fully supported.
This API is ideal for data visualization, custom UI elements, and dynamic graphics in HarmonyOS Next applications.
Top comments (0)