DEV Community

Cover image for Practical Guide to Custom Graphics with Canvas in HarmonyOS Next
kouwei qing
kouwei qing

Posted on

Practical Guide to Custom Graphics with Canvas in HarmonyOS Next

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:

  1. Direct Drawing on Canvas using CanvasRenderingContext2D.
  2. Offscreen Rendering (pre-rendering content in a buffer and converting it into an image for faster drawing).
  3. 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')  
  }  
}
Enter fullscreen mode Exit fullscreen mode

HarmonyOS Next Canvas Example

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:

  1. Use transferToImageBitmap() to convert the offscreen Canvas into an ImageBitmap.
  2. Use transferFromImageBitmap() to display the ImageBitmap 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%')  
  }  
}
Enter fullscreen mode Exit fullscreen mode

Steps:

  1. Create RenderingContextSettings (enabling anti-aliasing).
  2. Initialize OffscreenCanvas with a specified width and height.
  3. In onReady, get the offscreen context (getContext("2d", settings)).
  4. Draw shapes (e.g., strokeRect) on the offscreen Canvas.
  5. Convert the offscreen rendering to an ImageBitmap and transfer it to the main Canvas.

HarmonyOS Next Offscreen Rendering


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%')  
  }  
}
Enter fullscreen mode Exit fullscreen mode

HarmonyOS Next Line Drawing

(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%')  
  }  
}
Enter fullscreen mode Exit fullscreen mode

HarmonyOS Next Rectangle Drawing

(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%')  
  }  
}
Enter fullscreen mode Exit fullscreen mode

HarmonyOS Next Circle Drawing

(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%')  
  }  
}
Enter fullscreen mode Exit fullscreen mode

HarmonyOS Next Ellipse Drawing

(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%')  
  }  
}
Enter fullscreen mode Exit fullscreen mode

HarmonyOS Next Text Drawing


4. Additional Features

  • Image Drawing: Load and render images on Canvas.
  • Pixel Manipulation: Process image pixel data.
  • Gradients: Use createLinearGradient() and createRadialGradient() for smooth color transitions.

5. Summary

This guide explored custom graphics rendering in HarmonyOS Next using Canvas, covering:

  1. Direct Drawing with CanvasRenderingContext2D.
  2. Offscreen Rendering for performance optimization.
  3. 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)