Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Rendering Resource Images on Canvas in HarmonyOS NEXT

Tech May 17 2

To render image resources stored in the application package using the Canvas component, the image data must first be converted into a PixelMap or ImageBitmap object. Once converted, the drawImage method of the rendering context can be utilized to display the visual content.

Direct Initialization of ImageBitmap

If image assets are placed directly within the project's ets/common directory structure, they can be instantiated directly as an ImageBitmap.

private bitmapAsset: ImageBitmap = new ImageBitmap('common/assets/logo.png');

Converting Resource Manager Data to PixelMap

For resources managed by the system, a multi-step conversion process is required. The workflow involves retrieving the media content as a buffer via the ResourceManager, creating an ImageSource, and finally decoding it into a PixelMap.

@Entry
@Component
struct ResourceRenderer {
  private renderConfig: RenderingContextSettings = new RenderingContextSettings(true);
  private canvasCtx: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.renderConfig);

  async loadAndRenderImage() {
    const appContext = getContext(this);
    const resMgr: resourceManager.ResourceManager = appContext.resourceManager;
    // Retrieve the buffer for the specified resource ID
    const rawData: Uint8Array = await resMgr.getMediaContent($r('app.media.sample_image'));
    const sourceBuffer = rawData.buffer;
    
    // Create ImageSource and decode to PixelMap
    const imgSource: image.ImageSource = image.createImageSource(sourceBuffer);
    const targetMap: image.PixelMap = await imgSource.createPixelMap();
    
    // Draw the image onto the canvas context
    this.canvasCtx.drawImage(targetMap, 0, 0);
  }

  build() {
    Column({ space: 10 }) {
      Canvas(this.canvasCtx)
        .width(320)
        .height(320)
        .border({ width: 2, color: Color.Blue })
        .onReady(() => {
          this.loadAndRenderImage();
        })
    }
    .width('100%')
    .height('100%')
  }
}

Handling Touch Events on Canvas

The following example demonstrates how to interact with the rendered image by logging touch coordinates and event types. It extends the previous logic to include event handling.

import resourceManager from '@ohos.resourceManager';
import image from '@ohos.multimedia.image';

@Entry
@Component
struct CanvasInteractionDemo {
  private renderConfig: RenderingContextSettings = new RenderingContextSettings(true);
  private canvasCtx: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.renderConfig);
  @State touchLog: string = '';
  @State currentAction: string = '';

  async renderScene() {
    const appContext = getContext(this);
    const resMgr: resourceManager.ResourceManager = appContext.resourceManager;
    const rawData: Uint8Array = await resMgr.getMediaContent($r('app.media.sample_image'));
    const imgSource: image.ImageSource = image.createImageSource(rawData.buffer);
    const pixelMap: image.PixelMap = await imgSource.createPixelMap();
    
    this.canvasCtx.drawImage(pixelMap, 0, 0);
  }

  build() {
    Column({ space: 15 }) {
      Canvas(this.canvasCtx)
        .width(300)
        .height(300)
        .border({ width: 1, color: Color.Gray })
        .onReady(() => {
          this.renderScene();
        })
        .onTouch((event: TouchEvent) => {
          console.info(`Canvas Touch Event: ${JSON.stringify(event)}`);
          
          if (event) {
            switch (event.type) {
              case TouchType.Down:
                this.currentAction = 'Down';
                break;
              case TouchType.Up:
                this.currentAction = 'Up';
                break;
              case TouchType.Move:
                this.currentAction = 'Move';
                break;
            }
            
            const touchPoint = event.touches[0];
            const componentArea = event.target.area;
            
            this.touchLog = `Action: ${this.currentAction}\nPoint (x,y): ${touchPoint.x}, ${touchPoint.y}\n` +
              `Global Pos: (${componentArea.globalPosition.x}, ${componentArea.globalPosition.y})\n` +
              `Dimensions: ${componentArea.width} x ${componentArea.height}`;
          }
        })
      
      Text(this.touchLog)
        .fontSize(12)
        .fontColor(Color.Black)
    }
    .width('100%')
    .height('100%')
    .padding(10)
  }
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.