# OffscreenCanvas **OffscreenCanvas** provides an offscreen canvas for drawing. When using [Canvas](ts-components-canvas-canvas.md) or [Canvas API](ts-canvasrenderingcontext2d.md), rendering, animations, and user interactions generally occur on the main thread of an application. The computation relating to canvas animations and rendering may affect application performance. **OffscreenCanvas** allows for rendering off the screen. This means that some tasks can be run in a separate thread to reduce the load on the main thread. > **NOTE** > > The APIs of this module are supported since API version 8. Updates will be marked with a superscript to indicate their earliest API version. ## Child Components Not supported ## APIs OffscreenCanvas(width: number, height: number, unit?: LengthMetricsUnit) **Widget capability**: This API can be used in ArkTS widgets since API version 9. **Atomic service API**: This API can be used in atomic services since API version 11. **System capability**: SystemCapability.ArkUI.ArkUI.Full **Parameters** | Name | Type | Mandatory | Description | | ------ | -------- | ---- | ------------------------------------- | | width | number | Yes | Width of the offscreen canvas.
Default unit: vp | | height | number | Yes | Height of the offscreen canvas.
Default unit: vp | | unit12+ | [LengthMetricsUnit](../js-apis-arkui-graphics.md#lengthmetricsunit12) | No | Unit mode of the **OffscreenCanvas** object. The value cannot be dynamically changed once set. The configuration method is the same as that of [CanvasRenderingContext2D](ts-canvasrenderingcontext2d.md#lengthmetricsunit12).
Default value: **DEFAULT** | ## Attributes **Widget capability**: This API can be used in ArkTS widgets since API version 9. **Atomic service API**: This API can be used in atomic services since API version 11. **System capability**: SystemCapability.ArkUI.ArkUI.Full The following attributes are supported. | Name | Type | Read Only | Optional | Description | | ------ | ------ | ------ | ------- | ---- | | width | number | No | No | Width of the offscreen canvas.
Default unit: vp | | height | number | No | No | Height of the offscreen canvas.
Default unit: vp | ### width ```ts // xxx.ets @Entry @Component struct OffscreenCanvasPage { private settings: RenderingContextSettings = new RenderingContextSettings(true); private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); private offCanvas: OffscreenCanvas = new OffscreenCanvas(200, 300) build() { Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) { Column() { Canvas(this.context) .width('100%') .height('100%') .borderWidth(5) .borderColor('#057D02') .backgroundColor('#FFFFFF') .onReady(() => { let offContext = this.offCanvas.getContext("2d", this.settings) offContext.fillStyle = '#CDCDCD' offContext.fillRect(0, 0, this.offCanvas.width, 150) let image = this.offCanvas.transferToImageBitmap() this.context.setTransform(1, 0, 0, 1, 50, 200) this.context.transferFromImageBitmap(image) }) } }.width('100%').height('100%') } } ``` ![en-us_image_0000001194032666](figures/offscreen_canvas_width.png) ### height ```ts // xxx.ets @Entry @Component struct OffscreenCanvasPage { private settings: RenderingContextSettings = new RenderingContextSettings(true); private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); private offCanvas: OffscreenCanvas = new OffscreenCanvas(200, 300) build() { Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) { Column() { Canvas(this.context) .width('100%') .height('100%') .borderWidth(5) .borderColor('#057D02') .backgroundColor('#FFFFFF') .onReady(() => { let offContext = this.offCanvas.getContext("2d", this.settings) offContext.fillStyle = '#CDCDCD' offContext.fillRect(0, 0, 100, this.offCanvas.height) let image = this.offCanvas.transferToImageBitmap() this.context.setTransform(1, 0, 0, 1, 50, 200) this.context.transferFromImageBitmap(image) }) } }.width('100%').height('100%') } } ``` ![en-us_image_0000001194032666](figures/offscreen_canvas_height.png) ## Methods ### transferToImageBitmap transferToImageBitmap(): ImageBitmap Creates an **ImageBitmap** object from the most recently rendered image of the offscreen canvas. **Widget capability**: This API can be used in ArkTS widgets since API version 9. **Atomic service API**: This API can be used in atomic services since API version 11. **System capability**: SystemCapability.ArkUI.ArkUI.Full **Return value** | Type | Description | | -------------------------------------------------- | ----------------------- | | [ImageBitmap](ts-components-canvas-imagebitmap.md) | **ImageBitmap** object created. | **Example** ```ts // xxx.ets @Entry @Component struct OffscreenCanvasPage { private settings: RenderingContextSettings = new RenderingContextSettings(true) private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings) private offCanvas: OffscreenCanvas = new OffscreenCanvas(300, 500) build() { Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { Canvas(this.context) .width('100%') .height('100%') .borderWidth(5) .borderColor('#057D02') .backgroundColor('#FFFFFF') .onReady(() => { let offContext = this.offCanvas.getContext("2d", this.settings) offContext.fillStyle = '#CDCDCD' offContext.fillRect(0, 0, 300, 500) offContext.fillStyle = '#000000' offContext.font = '70px serif bold' offContext.fillText("Offscreen : Hello World!", 20, 60) let image = this.offCanvas.transferToImageBitmap() this.context.transferFromImageBitmap(image) }) } .width('100%') .height('100%') } } ``` ![zh-cn_image_0000001194032666](figures/offscreen_canvas_transferToImageBitmap.png) ### getContext10+ getContext(contextType: "2d", options?: RenderingContextSettings): OffscreenCanvasRenderingContext2D Obtains the drawing context of the offscreen canvas. **Atomic service API**: This API can be used in atomic services since API version 11. **System capability**: SystemCapability.ArkUI.ArkUI.Full **Parameters** | Name | Type | Mandatory | Description | | ----------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ | | contextType | string | Yes | Type of the drawing context of the offscreen canvas. The value can only be **"2d"**.
Default value: **"2d"**| | options | [RenderingContextSettings](ts-canvasrenderingcontext2d.md#renderingcontextsettings) | No | Parameters of the **OffscreenCanvasRenderingContext2D** object. For details, see [RenderingContextSettings](ts-canvasrenderingcontext2d.md#renderingcontextsettings).
Default value: **null** | **Return value** | Type | Description | | ------------------------------------------------------------ | --------------------------------- | | [OffscreenCanvasRenderingContext2D](ts-offscreencanvasrenderingcontext2d.md) | Drawing context of the offscreen canvas. If **contextType** in **getContext** is set to a value other than **"2d"** (including **null** and **undefined**), **null** is returned. | **Example** ```ts @Entry @Component struct OffscreenCanvasExamplePage { private settings: RenderingContextSettings = new RenderingContextSettings(true); private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); private offscreenCanvas: OffscreenCanvas = new OffscreenCanvas(600, 800) build() { Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) { Column() { Canvas(this.context) .width('100%') .height('100%') .backgroundColor('#FFFFFF') .onReady(() => { let offContext = this.offscreenCanvas.getContext("2d", this.settings) offContext.font = '70px sans-serif' offContext.fillText("Offscreen : Hello World!", 20, 60) offContext.fillStyle = "#0000ff" offContext.fillRect(230, 350, 50, 50) offContext.fillStyle = "#EE0077" offContext.translate(70, 70) offContext.fillRect(230, 350, 50, 50) offContext.fillStyle = "#77EE0077" offContext.translate(-70, -70) offContext.fillStyle = "#00ffff" offContext.rotate(45 * Math.PI / 180); offContext.fillRect(180, 120, 50, 50); offContext.rotate(-45 * Math.PI / 180); offContext.beginPath() offContext.moveTo(10, 150) offContext.bezierCurveTo(20, 100, 200, 100, 200, 20) offContext.stroke() offContext.fillStyle = '#FF00FF' offContext.fillRect(100, 100, 60, 60) let imageData = this.offscreenCanvas.transferToImageBitmap() this.context.transferFromImageBitmap(imageData) }) }.width('100%').height('100%') } .width('100%') .height('100%') } } ``` ![en-us_image_0000001194032666](figures/offscreen_canvas.png) ## Concurrent Thread Drawing Since API version 11, an application can call **postMessage** to pass an **OffscreenCanvas** instance to a worker thread for drawing, and call **onmessage** to receive the drawing result for display. > **NOTE** > > After the **OffscreenCanvas** instance uses **getContext** to obtain the drawing context, it cannot be passed to other threads through **postMessage**. Otherwise, an exception is thrown. > > After an **OffscreenCanvas** object is passed to a thread through **postMessage**, it cannot use the **getContext** or **transferToImageBitmap** APIs. Otherwise, an exception is thrown. > > After an **OffscreenCanvas** object is passed to a thread through **postMessage**, it cannot be passed to any other thread through **postMessage**. Otherwise, an exception is thrown. **Example** ```ts import { worker } from '@kit.ArkTS'; @Entry @Component struct OffscreenCanvasExamplePage { private settings: RenderingContextSettings = new RenderingContextSettings(true); private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); private myWorker = new worker.ThreadWorker('entry/ets/workers/Worker.ts'); build() { Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) { Column() { Canvas(this.context) .width('100%') .height('100%') .borderWidth(5) .borderColor('#057D02') .backgroundColor('#FFFFFF') .onReady(() => { let offCanvas = new OffscreenCanvas(600, 800) this.myWorker.postMessage({ myOffCanvas: offCanvas }); this.myWorker.onmessage = (e): void => { if (e.data.myImage) { let image: ImageBitmap = e.data.myImage this.context.transferFromImageBitmap(image) } } }) }.width('100%').height('100%') } .width('100%') .height('100%') } } ``` After the main thread sends the **OffscreenCanvas** instance through **postMessage**, the worker thread can receive it in **onmessage** for display. ```ts workerPort.onmessage = (e: MessageEvents) => { if (e.data.myOffCanvas) { let offCanvas: OffscreenCanvas = e.data.myOffCanvas let offContext = offCanvas.getContext("2d") offContext.fillStyle = '#CDCDCD' offContext.fillRect(0, 0, 200, 150) let image = offCanvas.transferToImageBitmap() workerPort.postMessage({ myImage: image }); } } ``` ![en-us_image_0000001194032666](figures/offscreen_canvas_width.png)