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![en-us_image_0000001194032666](figures/offscreen_canvas_width.png)
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![en-us_image_0000001194032666](figures/offscreen_canvas_height.png)
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![zh-cn_image_0000001194032666](figures/offscreen_canvas_transferToImageBitmap.png)
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![en-us_image_0000001194032666](figures/offscreen_canvas.png)
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![en-us_image_0000001194032666](figures/offscreen_canvas_width.png)
321