1# Drawing Custom Graphics Using the Canvas (Canvas) 2 3 4**Canvas** provides a canvas component for drawing custom graphics. You can use the **CanvasRenderingContext2D** and **OffscreenCanvasRenderingContext2D** objects to draw graphics on the **Canvas** component. The drawing objects can be basic shapes, text, and images. 5 6 7## Drawing Custom Graphics on the Canvas 8 9You can draw custom graphics on the canvas in any of the following ways: 10 11 12- Use [CanvasRenderingContext2D](../reference/arkui-ts/ts-canvasrenderingcontext2d.md). 13 14 ```ts 15 @Entry 16 @Component 17 struct CanvasExample1 { 18 // Configure the parameters of the CanvasRenderingContext2D object, including whether to enable anti-aliasing. The value true indicates that anti-aliasing is enabled. 19 private settings: RenderingContextSettings = new RenderingContextSettings(true) 20 // Create a CanvasRenderingContext2D object by calling CanvasRenderingContext2D object in Canvas. 21 private context: CanvasRenderingContext2D= new CanvasRenderingContext2D(this.settings) 22 build() { 23 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 24 // Invoke the CanvasRenderingContext2D object in Canvas. 25 Canvas(this.context) 26 .width('100%') 27 .height('100%') 28 .backgroundColor('#F5DC62') 29 .onReady(() =>{ 30 // You can draw content here. 31 this.context.strokeRect(50, 50, 200, 150); 32 }) 33 } 34 .width('100%') 35 .height('100%') 36 } 37 } 38 39 ``` 40 41 .jpg) 42 43- Drawing offscreen onto a canvas is a process where content to draw onto the canvas is first drawn in the buffer, and then converted into a picture, and finally the picture is drawn on the canvas. This process increases the drawing efficiency. Specifically, the implementation is as follows: 44 1. Use the **transferToImageBitmap** API to create an **ImageBitmap** object for the image that is recently rendered off the screen canvas. 45 2. Use the **transferFromImageBitmap** API of the **CanvasRenderingContext2D** object to display the created **ImageBitmap** object. 46 47 For details, see [OffscreenCanvasRenderingContext2D](../reference/arkui-ts/ts-offscreencanvasrenderingcontext2d.md). 48 49 ```ts 50 @Entry 51 @Component 52 struct CanvasExample2 { 53 // Configure the parameters of the CanvasRenderingContext2D and OffscreenCanvasRenderingContext2D objects, including whether to enable anti-aliasing. The value true indicates that anti-aliasing is enabled. 54 private settings: RenderingContextSettings = new RenderingContextSettings(true) 55 private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings) 56 // Create an OffscreenCanvas object. width indicates the width of the offscreen canvas, and height indicates the height of the offscreen canvas. 57 private offCanvas: OffscreenCanvas = new OffscreenCanvas(600, 600) 58 59 build() { 60 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 61 Canvas(this.context) 62 .width('100%') 63 .height('100%') 64 .backgroundColor('#F5DC62') 65 .onReady(() =>{ 66 let offContext = this.offCanvas.getContext("2d", this.settings) 67 // You can draw content here. 68 offContext.strokeRect(50, 50, 200, 150); 69 // Display the image rendered by the offscreen drawing value on the common canvas. 70 let image = this.offCanvas.transferToImageBitmap(); 71 this.context.transferFromImageBitmap(image); 72 }) 73 } 74 .width('100%') 75 .height('100%') 76 } 77 } 78 79 ``` 80 81 .jpg) 82 83 >**NOTE** 84 > 85 >The APIs called for drawing on the canvas through the **CanvasRenderingContext2D** and **OffscreenCanvasRenderingContext2D** objects are the same. Unless otherwise specified, the value unit of the parameters in these APIs is vp. 86 87- Before loading the Lottie animation on the canvas, download the Lottie as follows: 88 89 ```ts 90 import lottie from '@ohos/lottie' 91 ``` 92 93 For details about the APIs, see [Lottie](https://gitee.com/openharmony-tpc/lottieETS). 94 95 96## Initializing the Canvas Component 97 98**onReady(event: () => void)** is the event callback when the **Canvas** component initialization is complete. After this event is called, the determined width and height of the **Canvas** component can be obtained. The **CanvasRenderingContext2D** and **OffscreenCanvasRenderingContext2D** objects can then be used to call related APIs to draw graphics. 99 100```ts 101Canvas(this.context) 102 .width('100%') 103 .height('100%') 104 .backgroundColor('#F5DC62') 105 .onReady(() => { 106 this.context.fillStyle = '#0097D4'; 107 this.context.fillRect(50, 50, 100, 100); 108 }) 109``` 110 111.jpg) 112 113 114## Canvas Component Drawing Modes 115 116Two modes are available for drawing with the **Canvas** component: 117 118- After the **onReady()** callback of the **Canvas** component is invoked, use the **CanvasRenderingContext2D** and **OffscreenCanvasRenderingContext2D** objects to call related APIs for drawing. 119 120 ```ts 121 Canvas(this.context) 122 .width('100%') 123 .height('100%') 124 .backgroundColor('#F5DC62') 125 .onReady(() =>{ 126 this.context.beginPath(); 127 this.context.moveTo(50, 50); 128 this.context.lineTo(280, 160); 129 this.context.stroke(); 130 }) 131 ``` 132 133 .jpg) 134 135- Define an individual **path2d** object to build an ideal path, and then call the **stroke** or **fill** API of the **CanvasRenderingContext2D** and **OffscreenCanvasRenderingContext2D** objects to draw the path. For details, see [Path2D](../reference/arkui-ts/ts-components-canvas-path2d.md). 136 137 ```ts 138 Canvas(this.context) 139 .width('100%') 140 .height('100%') 141 .backgroundColor('#F5DC62') 142 .onReady(() =>{ 143 let region = new Path2D(); 144 region.arc(100, 75, 50, 0, 6.28); 145 this.context.stroke(region); 146 }) 147 ``` 148 149 .jpg) 150 151 152## Common Usage of the Canvas Component 153 154**OffscreenCanvasRenderingContext2D** and **CanvasRenderingContext2D** provide a large number of attributes and methods, which can be used to draw text and graphics and process pixels. They are the core of the **Canvas** component. Common APIs include [fill](../reference/arkui-ts/ts-canvasrenderingcontext2d.md#fill), [clip](../reference/arkui-ts/ts-canvasrenderingcontext2d.md#clip), and [stroke](../reference/arkui-ts/ts-canvasrenderingcontext2d.md#stroke). In addition, attributes such as [fillStyle](../reference/arkui-ts/ts-canvasrenderingcontext2d.md#fillstyle), [globalAlpha](../reference/arkui-ts/ts-canvasrenderingcontext2d.md#globalalpha), and [strokeStyle](../reference/arkui-ts/ts-canvasrenderingcontext2d.md#strokestyle) are provided to spruce up the graphics. This topic describes typical usage of the canvas. 155 156- Draw a basic shape. 157 You can draw a basic shape by calling APIs such as [arc](../reference/arkui-ts/ts-canvasrenderingcontext2d.md#arc), [ellipse](../reference/arkui-ts/ts-canvasrenderingcontext2d.md#ellipse), and [rect](../reference/arkui-ts/ts-canvasrenderingcontext2d.md#rect). 158 159 ```ts 160 Canvas(this.context) 161 .width('100%') 162 .height('100%') 163 .backgroundColor('#F5DC62') 164 .onReady(() =>{ 165 // Draw a rectangle. 166 this.context.beginPath(); 167 this.context.rect(100, 50, 100, 100); 168 this.context.stroke(); 169 // Draw a circle on the canvas. 170 this.context.beginPath(); 171 this.context.arc(150, 250, 50, 0, 6.28); 172 this.context.stroke(); 173 // Draw an oval on the canvas. 174 this.context.beginPath(); 175 this.context.ellipse(150, 450, 50, 100, Math.PI * 0.25, Math.PI * 0, Math.PI * 2); 176 this.context.stroke(); 177 }) 178 ``` 179 180 .jpg) 181 182- Draw text. 183 184 You can use APIs such as [fillText](../reference/arkui-ts/ts-canvasrenderingcontext2d.md#filltext) and [strokeText](../reference/arkui-ts/ts-canvasrenderingcontext2d.md#stroketext) to draw text. 185 186 ```ts 187 Canvas(this.context) 188 .width('100%') 189 .height('100%') 190 .backgroundColor('#F5DC62') 191 .onReady(() =>{ 192 // Draw filled text on the canvas. 193 this.context.font = '50px sans-serif'; 194 this.context.fillText("Hello World!", 50, 100); 195 // Draw a text stroke on the canvas. 196 this.context.font = '55px sans-serif'; 197 this.context.strokeText("Hello World!", 50, 150); 198 }) 199 ``` 200 201 .jpg) 202 203- Draw images and processes image pixel information. 204 205 You can draw an image by calling APIs such as [drawImage](../reference/arkui-ts/ts-canvasrenderingcontext2d.md#drawimage) and [putImageData](../reference/arkui-ts/ts-canvasrenderingcontext2d.md#putimagedata). You can also process image pixel information by calling APIs such as [createImageData](../reference/arkui-ts/ts-canvasrenderingcontext2d.md#createimagedata), [getPixelMap](../reference/arkui-ts/ts-canvasrenderingcontext2d.md#getpixelmap), and [getImageData](../reference/arkui-ts/ts-canvasrenderingcontext2d.md#getimagedata). 206 207 ```ts 208 @Entry 209 @Component 210 struct GetImageData { 211 private settings: RenderingContextSettings = new RenderingContextSettings(true) 212 private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings) 213 private offCanvas: OffscreenCanvas = new OffscreenCanvas(600, 600) 214 private img:ImageBitmap = new ImageBitmap("/common/images/1234.png") 215 216 build() { 217 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 218 Canvas(this.context) 219 .width('100%') 220 .height('100%') 221 .backgroundColor('#F5DC62') 222 .onReady(() =>{ 223 let offContext = this.offCanvas.getContext("2d", this.settings) 224 // Use the drawImage API to draw an image in the area with the width and height of 130 starting from (0, 0). 225 offContext.drawImage(this.img,0,0,130,130); 226 // Use the getImageData API to obtain the image data with the width and height of 130 starting from (50, 50). 227 let imagedata = offContext.getImageData(50,50,130,130); 228 // Use the putImageData API to draw the obtained image data in the area starting from (150, 150). 229 offContext.putImageData(imagedata,150,150); 230 // Draw the offscreen drawing content to the canvas. 231 let image = this.offCanvas.transferToImageBitmap(); 232 this.context.transferFromImageBitmap(image); 233 }) 234 } 235 .width('100%') 236 .height('100%') 237 } 238 } 239 ``` 240 241  242 243- Other usage 244 245 **Canvas** also provides other usage. For example, regarding [CanvasGradient](../reference/arkui-ts/ts-components-canvas-canvasgradient.md), you can create a linear gradient with [createLinearGradient](../reference/arkui-ts/ts-canvasrenderingcontext2d.md#createlineargradient) or create a radial gradient with [createRadialGradient](../reference/arkui-ts/ts-canvasrenderingcontext2d.md#createradialgradient), among others. 246 247 ```ts 248 Canvas(this.context) 249 .width('100%') 250 .height('100%') 251 .backgroundColor('#F5DC62') 252 .onReady(() =>{ 253 // Create a CanvasGradient object with radial gradient colors. 254 let grad = this.context.createRadialGradient(200,200,50, 200,200,200) 255 // Set the gradient color stop for the CanvasGradient object, including the offset and colors. 256 grad.addColorStop(0.0, '#E87361'); 257 grad.addColorStop(0.5, '#FFFFF0'); 258 grad.addColorStop(1.0, '#BDDB69'); 259 // Fill the rectangle with the CanvasGradient object. 260 this.context.fillStyle = grad; 261 this.context.fillRect(0, 0, 400, 400); 262 }) 263 ``` 264 265 .jpg) 266 267 268## Example Scenario 269 270- Draw a basic shape. 271 272 ```ts 273 @Entry 274 @Component 275 struct ClearRect { 276 private settings: RenderingContextSettings = new RenderingContextSettings(true); 277 private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); 278 279 build() { 280 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 281 Canvas(this.context) 282 .width('100%') 283 .height('100%') 284 .backgroundColor('#F5DC62') 285 .onReady(() =>{ 286 // Set the fill color to blue. 287 this.context.fillStyle = '#0097D4'; 288 // Take (50, 50) as the upper left corner and draw a rectangle with the width and height of 200. 289 this.context.fillRect(50,50,200,200); 290 // Use (70, 70) as the upper left corner and clear the area with the width of 150 and height of 100. 291 this.context.clearRect(70,70,150,100); 292 }) 293 } 294 .width('100%') 295 .height('100%') 296 } 297 } 298 299 ``` 300 301 .jpg) 302 303- Draw an irregular shape. 304 305 ```ts 306 @Entry 307 @Component 308 struct Path2d { 309 private settings: RenderingContextSettings = new RenderingContextSettings(true); 310 private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); 311 312 build() { 313 Row() { 314 Column() { 315 Canvas(this.context) 316 .width('100%') 317 .height('100%') 318 .backgroundColor('#F5DC62') 319 .onReady(() =>{ 320 // Use the Path2D API to create a pentagon. 321 let path = new Path2D(); 322 path.moveTo(150, 50); 323 path.lineTo(50, 150); 324 path.lineTo(100, 250); 325 path.lineTo(200, 250); 326 path.lineTo(250, 150); 327 path.closePath(); 328 // Set the fill color to blue. 329 this.context.fillStyle = '#0097D4'; 330 // Draw the pentagon described by Path2D in the canvas in fill mode. 331 this.context.fill(path); 332 }) 333 } 334 .width('100%') 335 } 336 .height('100%') 337 } 338 } 339 ``` 340 341  342