• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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![en-us_image_0000001194032666](figures/offscreen_canvas_width.png)
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![en-us_image_0000001194032666](figures/offscreen_canvas_height.png)
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![zh-cn_image_0000001194032666](figures/offscreen_canvas_transferToImageBitmap.png)
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![en-us_image_0000001194032666](figures/offscreen_canvas.png)
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![en-us_image_0000001194032666](figures/offscreen_canvas_width.png)
302