1# OffscreenCanvas 2 3**OffscreenCanvas** provides an offscreen canvas for drawing. 4 5When 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. 6 7> **NOTE** 8> 9> The APIs of this module are supported since API version 8. Updates will be marked with a superscript to indicate their earliest API version. 10 11## Child Components 12 13Not supported 14 15## APIs 16 17OffscreenCanvas(width: number, height: number, unit?: LengthMetricsUnit) 18 19**Widget capability**: This API can be used in ArkTS widgets since API version 9. 20 21**Atomic service API**: This API can be used in atomic services since API version 11. 22 23**System capability**: SystemCapability.ArkUI.ArkUI.Full 24 25**Parameters** 26 27| Name | Type | Mandatory | Description | 28| ------ | -------- | ---- | ------------------------------------- | 29| width | number | Yes | Width of the offscreen canvas.<br>Default unit: vp | 30| height | number | Yes | Height of the offscreen canvas.<br>Default unit: vp | 31| unit<sup>12+</sup> | [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).<br>Default value: **DEFAULT** | 32 33## Attributes 34 35**Widget capability**: This API can be used in ArkTS widgets since API version 9. 36 37**Atomic service API**: This API can be used in atomic services since API version 11. 38 39**System capability**: SystemCapability.ArkUI.ArkUI.Full 40 41The following attributes are supported. 42 43| Name | Type | Read Only | Optional | Description | 44| ------ | ------ | ------ | ------- | ---- | 45| width | number | No | No | Width of the offscreen canvas.<br>Default unit: vp | 46| height | number | No | No | Height of the offscreen canvas.<br>Default unit: vp | 47 48### width 49 50```ts 51// xxx.ets 52@Entry 53@Component 54struct OffscreenCanvasPage { 55 private settings: RenderingContextSettings = new RenderingContextSettings(true); 56 private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); 57 private offCanvas: OffscreenCanvas = new OffscreenCanvas(200, 300) 58 59 build() { 60 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) { 61 Column() { 62 Canvas(this.context) 63 .width('100%') 64 .height('100%') 65 .borderWidth(5) 66 .borderColor('#057D02') 67 .backgroundColor('#FFFFFF') 68 .onReady(() => { 69 let offContext = this.offCanvas.getContext("2d", this.settings) 70 offContext.fillStyle = '#CDCDCD' 71 offContext.fillRect(0, 0, this.offCanvas.width, 150) 72 let image = this.offCanvas.transferToImageBitmap() 73 this.context.setTransform(1, 0, 0, 1, 50, 200) 74 this.context.transferFromImageBitmap(image) 75 }) 76 } 77 }.width('100%').height('100%') 78 } 79} 80``` 81 82 83 84### height 85 86```ts 87// xxx.ets 88@Entry 89@Component 90struct OffscreenCanvasPage { 91 private settings: RenderingContextSettings = new RenderingContextSettings(true); 92 private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); 93 private offCanvas: OffscreenCanvas = new OffscreenCanvas(200, 300) 94 95 build() { 96 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) { 97 Column() { 98 Canvas(this.context) 99 .width('100%') 100 .height('100%') 101 .borderWidth(5) 102 .borderColor('#057D02') 103 .backgroundColor('#FFFFFF') 104 .onReady(() => { 105 let offContext = this.offCanvas.getContext("2d", this.settings) 106 offContext.fillStyle = '#CDCDCD' 107 offContext.fillRect(0, 0, 100, this.offCanvas.height) 108 let image = this.offCanvas.transferToImageBitmap() 109 this.context.setTransform(1, 0, 0, 1, 50, 200) 110 this.context.transferFromImageBitmap(image) 111 }) 112 } 113 }.width('100%').height('100%') 114 } 115} 116``` 117 118 119 120## Methods 121 122### transferToImageBitmap 123 124transferToImageBitmap(): ImageBitmap 125 126Creates an **ImageBitmap** object from the most recently rendered image of the offscreen canvas. 127 128**Widget capability**: This API can be used in ArkTS widgets since API version 9. 129 130**Atomic service API**: This API can be used in atomic services since API version 11. 131 132**System capability**: SystemCapability.ArkUI.ArkUI.Full 133 134**Return value** 135 136| Type | Description | 137| -------------------------------------------------- | ----------------------- | 138| [ImageBitmap](ts-components-canvas-imagebitmap.md) | **ImageBitmap** object created. | 139 140**Example** 141 142```ts 143// xxx.ets 144@Entry 145@Component 146struct OffscreenCanvasPage { 147 private settings: RenderingContextSettings = new RenderingContextSettings(true) 148 private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings) 149 private offCanvas: OffscreenCanvas = new OffscreenCanvas(300, 500) 150 151 build() { 152 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 153 Canvas(this.context) 154 .width('100%') 155 .height('100%') 156 .borderWidth(5) 157 .borderColor('#057D02') 158 .backgroundColor('#FFFFFF') 159 .onReady(() => { 160 let offContext = this.offCanvas.getContext("2d", this.settings) 161 offContext.fillStyle = '#CDCDCD' 162 offContext.fillRect(0, 0, 300, 500) 163 offContext.fillStyle = '#000000' 164 offContext.font = '70px serif bold' 165 offContext.fillText("Offscreen : Hello World!", 20, 60) 166 let image = this.offCanvas.transferToImageBitmap() 167 this.context.transferFromImageBitmap(image) 168 }) 169 } 170 .width('100%') 171 .height('100%') 172 } 173} 174``` 175 176 177 178### getContext<sup>10+</sup> 179 180getContext(contextType: "2d", options?: RenderingContextSettings): OffscreenCanvasRenderingContext2D 181 182Obtains the drawing context of the offscreen canvas. 183 184**Atomic service API**: This API can be used in atomic services since API version 11. 185 186**System capability**: SystemCapability.ArkUI.ArkUI.Full 187 188**Parameters** 189 190| Name | Type | Mandatory | Description | 191| ----------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ | 192| contextType | string | Yes | Type of the drawing context of the offscreen canvas. The value can only be **"2d"**.<br>Default value: **"2d"**| 193| options | [RenderingContextSettings](ts-canvasrenderingcontext2d.md#renderingcontextsettings) | No | Parameters of the **OffscreenCanvasRenderingContext2D** object. For details, see [RenderingContextSettings](ts-canvasrenderingcontext2d.md#renderingcontextsettings).<br>Default value: **null** | 194 195**Return value** 196 197| Type | Description | 198| ------------------------------------------------------------ | --------------------------------- | 199| [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. | 200 201**Example** 202 203```ts 204@Entry 205@Component 206struct OffscreenCanvasExamplePage { 207 private settings: RenderingContextSettings = new RenderingContextSettings(true); 208 private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); 209 private offscreenCanvas: OffscreenCanvas = new OffscreenCanvas(600, 800) 210 211 build() { 212 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) { 213 Column() { 214 Canvas(this.context) 215 .width('100%') 216 .height('100%') 217 .backgroundColor('#FFFFFF') 218 .onReady(() => { 219 let offContext = this.offscreenCanvas.getContext("2d", this.settings) 220 offContext.font = '70px sans-serif' 221 offContext.fillText("Offscreen : Hello World!", 20, 60) 222 offContext.fillStyle = "#0000ff" 223 offContext.fillRect(230, 350, 50, 50) 224 offContext.fillStyle = "#EE0077" 225 offContext.translate(70, 70) 226 offContext.fillRect(230, 350, 50, 50) 227 offContext.fillStyle = "#77EE0077" 228 offContext.translate(-70, -70) 229 offContext.fillStyle = "#00ffff" 230 offContext.rotate(45 * Math.PI / 180); 231 offContext.fillRect(180, 120, 50, 50); 232 offContext.rotate(-45 * Math.PI / 180); 233 offContext.beginPath() 234 offContext.moveTo(10, 150) 235 offContext.bezierCurveTo(20, 100, 200, 100, 200, 20) 236 offContext.stroke() 237 offContext.fillStyle = '#FF00FF' 238 offContext.fillRect(100, 100, 60, 60) 239 let imageData = this.offscreenCanvas.transferToImageBitmap() 240 this.context.transferFromImageBitmap(imageData) 241 }) 242 }.width('100%').height('100%') 243 } 244 .width('100%') 245 .height('100%') 246 } 247} 248``` 249 250 251 252 253## Concurrent Thread Drawing 254 255Since 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. 256 257> **NOTE** 258> 259> 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. 260> 261> After an **OffscreenCanvas** object is passed to a thread through **postMessage**, it cannot use the **getContext** or **transferToImageBitmap** APIs. Otherwise, an exception is thrown. 262> 263> 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. 264 265**Example** 266 267```ts 268import { worker } from '@kit.ArkTS'; 269 270@Entry 271@Component 272struct OffscreenCanvasExamplePage { 273 private settings: RenderingContextSettings = new RenderingContextSettings(true); 274 private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); 275 private myWorker = new worker.ThreadWorker('entry/ets/workers/Worker.ts'); 276 277 build() { 278 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Start }) { 279 Column() { 280 Canvas(this.context) 281 .width('100%') 282 .height('100%') 283 .borderWidth(5) 284 .borderColor('#057D02') 285 .backgroundColor('#FFFFFF') 286 .onReady(() => { 287 let offCanvas = new OffscreenCanvas(600, 800) 288 this.myWorker.postMessage({ myOffCanvas: offCanvas }); 289 this.myWorker.onmessage = (e): void => { 290 if (e.data.myImage) { 291 let image: ImageBitmap = e.data.myImage 292 this.context.transferFromImageBitmap(image) 293 } 294 } 295 296 }) 297 }.width('100%').height('100%') 298 } 299 .width('100%') 300 .height('100%') 301 } 302} 303``` 304 305After the main thread sends the **OffscreenCanvas** instance through **postMessage**, the worker thread can receive it in **onmessage** for display. 306 307```ts 308workerPort.onmessage = (e: MessageEvents) => { 309 if (e.data.myOffCanvas) { 310 let offCanvas: OffscreenCanvas = e.data.myOffCanvas 311 let offContext = offCanvas.getContext("2d") 312 offContext.fillStyle = '#CDCDCD' 313 offContext.fillRect(0, 0, 200, 150) 314 let image = offCanvas.transferToImageBitmap() 315 workerPort.postMessage({ myImage: image }); 316 } 317} 318``` 319 320 321