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