1# CanvasRenderingContext2D 2 3 4Use **CanvasRenderingContext2D** to draw objects such as graphics, texts, line segments, and images on the **<canvas>** component. For details, see [CanvasRenderingContext2D](../reference/arkui-js/js-components-canvas-canvasrenderingcontext2d.md). 5 6 7## Drawing Line Segments 8 9Use **moveTo** and **lineTo** to draw a line segment. Use the **closePath** method to end current path, obtaining a closed path. Set **quadraticCurveTo** (quadratic bezier curve) or **bezierCurveTo** (cubic bezier curve) to draw a graphic. 10 11 12```html 13<!-- xxx.hml --> 14<div class="container"> 15 <canvas ref="canvas1"></canvas> 16 <select @change="change"> 17 <option value="value1"> line </option> 18 <option value="value2"> quadratic </option> 19 <option value="value3"> bezier </option> 20 <option value="value4"> arc/ellipse </option> 21 <option value="value5"> lineJoin/miterLimit </option> 22 </select> 23</div> 24``` 25 26 27```css 28/* xxx.css */ 29.container{ 30 width: 100%; 31 height: 100%; 32 flex-direction: column; 33 justify-content: center; 34 align-items: center; 35 background-color: #F1F3F5; 36} 37canvas{ 38 width: 600px; 39 height: 500px; 40 background-color: #fdfdfd; 41 border: 5px solid red; 42} 43select{ 44 margin-top: 50px; 45 width: 250px; 46 height: 100px; 47 background-color: white; 48} 49``` 50 51 52```js 53// xxx.js 54export default { 55 data:{ 56 el: null, 57 ctx: null, 58 }, 59 onShow(){ 60 this.el = this.$refs.canvas1; 61 this.ctx = this.el.getContext("2d",{antialias: true}); 62 // Clear the contents on the canvas. 63 this.ctx.clearRect(0, 0, 600, 500); 64 // Create a drawing path. 65 this.ctx.beginPath(); 66 // Square off the endpoints of the line. 67 this.ctx.lineCap = 'butt'; 68 // Border width 69 this.ctx.lineWidth = 15; 70 // Create a drawing path. 71 this.ctx.beginPath(); 72 // Move a drawing path from the current point to a target position. 73 this.ctx.moveTo(200, 100); 74 // Connect the current point to a target position. 75 this.ctx.lineTo(400, 100); 76 // Stroke a path. 77 this.ctx.stroke(); 78 this.ctx.beginPath(); 79 // Round the endpoints of the line. 80 this.ctx.lineCap = 'round'; 81 this.ctx.moveTo(200, 200); 82 this.ctx.lineTo(400, 200); 83 this.ctx.stroke(); 84 // Square off the endpoints of the line. 85 this.ctx.beginPath(); 86 this.ctx.lineCap = 'square'; 87 this.ctx.moveTo(200, 300); 88 this.ctx.lineTo(400, 300); 89 this.ctx.stroke(); 90 }, 91 change(e){ 92 if(e.newValue == 'value1'){ 93 this.el = this.$refs.canvas1; 94 this.ctx = this.el.getContext("2d",{antialias: true}); 95 this.ctx.clearRect(0, 0, 600, 500); 96 // Top 97 this.ctx.beginPath(); 98 this.ctx.lineCap = 'butt'; 99 this.ctx.moveTo(200, 100); 100 this.ctx.lineTo(400, 100); 101 this.ctx.stroke(); 102 // Center 103 this.ctx.beginPath(); 104 this.ctx.lineCap = 'round'; 105 this.ctx.moveTo(200, 200); 106 this.ctx.lineTo(400, 200); 107 this.ctx.stroke(); 108 // Bottom 109 this.ctx.beginPath(); 110 this.ctx.lineCap = 'square'; 111 this.ctx.moveTo(200, 300); 112 this.ctx.lineTo(400, 300); 113 this.ctx.stroke(); 114 }else if(e.newValue == 'value2'){ 115 this.ctx.clearRect(0, 0, 600, 500); 116 // Top 117 this.ctx.beginPath(); 118 this.ctx.moveTo(100, 150); 119 // Path of the quadratic bezier curve 120 this.ctx.quadraticCurveTo(300, 50, 500, 150); 121 this.ctx.stroke(); 122 // Left 123 this.ctx.beginPath(); 124 this.ctx.moveTo(200, 150); 125 this.ctx.quadraticCurveTo(250, 250, 250, 400); 126 this.ctx.stroke(); 127 // Right 128 this.ctx.beginPath(); 129 this.ctx.moveTo(400, 150); 130 this.ctx.quadraticCurveTo(350, 250, 350, 400); 131 this.ctx.stroke(); 132 }else if(e.newValue == 'value3'){ 133 this.ctx.clearRect(0, 0, 600, 500); 134 // Bottom 135 this.ctx.beginPath(); 136 this.ctx.moveTo(100, 200); 137 // Path of the cubic bezier curve 138 this.ctx.bezierCurveTo(150, 100, 200, 100,250, 200); 139 this.ctx.stroke(); 140 // Left 141 this.ctx.beginPath(); 142 this.ctx.moveTo(350, 200); 143 this.ctx.bezierCurveTo(400, 100, 450, 100,500, 200); 144 this.ctx.stroke(); 145 // Right 146 this.ctx.beginPath(); 147 this.ctx.moveTo(200, 350); 148 this.ctx.bezierCurveTo(250, 500, 350, 500, 400, 350); 149 this.ctx.stroke(); 150 }else if(e.newValue == 'value4'){ 151 this.ctx.clearRect(0, 0, 600, 500); 152 this.ctx.beginPath(); 153 this.ctx.moveTo(100, 200); 154 // Arc 155 this.ctx.arcTo(150, 300, 350, 300, 150); 156 this.ctx.stroke(); 157 this.ctx.beginPath(); 158 // Ellipse 159 this.ctx.ellipse(400, 250, 50, 100, Math.PI * 0.25, Math.PI * 0.5 , Math.PI , 1); 160 this.ctx.stroke(); 161 }else if(e.newValue == 'value5'){ 162 this.ctx.clearRect(0, 0, 600, 500); 163 // Upper left 164 this.ctx.beginPath(); 165 // Draw a sector centered at the common endpoint of connected line segments. 166 this.ctx.lineJoin = 'round'; 167 this.ctx.moveTo(100, 100); 168 this.ctx.lineTo(200, 200); 169 this.ctx.lineTo(100, 250); 170 this.ctx.stroke(); 171 // lower left 172 this.ctx.beginPath(); 173 // Fill a triangular between the common endpoint of connected segments. 174 this.ctx.lineJoin = 'bevel'; 175 this.ctx.moveTo(100, 300); 176 this.ctx.lineTo(200, 400); 177 this.ctx.lineTo(100, 450); 178 this.ctx.stroke(); 179 // Top right 180 this.ctx.beginPath(); 181 // Distance between the internal angle and exterior angle at the intersection of lines 182 this.ctx.lineJoin = 'miter'; 183 this.ctx.miterLimit = 3; 184 this.ctx.moveTo(400, 100); 185 this.ctx.lineTo(450, 200); 186 this.ctx.lineTo(400, 250); 187 // Draw a closed path. 188 this.ctx.closePath(); 189 this.ctx.stroke(); 190 // Lower right 191 this.ctx.beginPath(); 192 this.ctx.lineJoin = 'miter'; 193 this.ctx.miterLimit = 10; 194 this.ctx.moveTo(400, 300); 195 this.ctx.lineTo(450, 400); 196 this.ctx.lineTo(400, 450); 197 this.ctx.closePath(); 198 this.ctx.stroke(); 199 } 200 }, 201} 202``` 203 204![en-us_image_0000001232162320](figures/en-us_image_0000001232162320.gif) 205 206 207## Drawing Border 208 209Globally define the canvas (**el**) and brush (**ctx**), and create a rectangle with the border width of 5 upon initialization. Change the border width (**lineWidth**), color (**strokeStyle**), and line dash level (**setLineDash**). Add the **change** event to the **<select>** component. The **change** event will be triggered upon selection and the changed image will be displayed. 210 211 212 213```html 214<!-- xxx.hml --> 215<div class="container"> 216 <canvas ref="canvas1"></canvas> 217 <select @change="change"> 218 <option value="value1">strokeRect</option> 219 <option value="value2">arc</option> 220 <option value="value3">lineDashRect</option> 221 <option value="value4">fillRect</option> 222 </select> 223</div> 224``` 225 226 227 228```css 229/* xxx.css */ 230.container{ 231 width: 100%; 232 height: 100%; 233 flex-direction: column; 234 justify-content: center; 235 align-items: center; 236 background-color: #F1F3F5; 237} 238canvas{ 239 width: 600px; 240 height: 500px; 241 background-color: #fdfdfd; 242 border: 5px solid red; 243} 244select{ 245 margin-top: 50px; 246 width: 250px; 247 height: 100px; 248 background-color: white; 249} 250``` 251 252 253 254```js 255// xxx.js 256export default { 257 data:{ 258 el: null, 259 ctx: null, 260 }, 261 onShow(){ 262 this.el = this.$refs.canvas1; 263 this.ctx = this.el.getContext("2d",{antialias: true}); 264 this.ctx.lineWidth = 5; 265 this.ctx.strokeRect(200, 150, 200, 200); 266 }, 267 change(e){ 268 if(e.newValue == 'value1'){ 269 // Clear the contents on the canvas. 270 this.ctx.clearRect(0,0,600,500); 271 // Border width 272 this.ctx.lineWidth = 5; 273 // Border color 274 this.ctx.strokeStyle = '#110000'; 275 // Line dash level of the border 276 this.ctx.setLineDash([0,0]); 277 // Draw a stroked rectangle. 278 this.ctx.strokeRect(200, 150, 200, 200); 279 }else if (e.newValue == 'value2'){ 280 this.ctx.clearRect(0,0,600,500); 281 this.ctx.lineWidth = 30; 282 this.ctx.strokeStyle = '#0000ff'; 283 this.ctx.setLineDash([0,0]); 284 // Draw a circle. 285 this.ctx.arc(300, 250, 150,0,6.28); 286 // Draw borders. 287 this.ctx.stroke(); 288 }else if (e.newValue == 'value3'){ 289 this.ctx.clearRect(0,0,600,500); 290 this.ctx.lineWidth = 5; 291 this.ctx.setLineDash([5,5]); 292 this.ctx.strokeRect(200, 150, 200, 200); 293 }else if (e.newValue == 'value4'){ 294 this.ctx.clearRect(0,0,600,500); 295 // Draw and fill a rectangle. 296 this.ctx.fillStyle = '#0000ff'; 297 this.ctx.fillRect(200, 150, 200, 200); 298 } 299 }, 300} 301``` 302 303 304![en-us_image_0000001232003004](figures/en-us_image_0000001232003004.gif) 305 306 307## Setting Gradient Fill Colors 308 309Add the **createLinearGradient** and **createRadialGradient** attributes to create a gradient container, use the **addColorStop** method to add multiple color blocks to form a gradient color, and set **fillStyle** as **gradient** to apply the gradient color to a rectangle. Then set the shadow blur level by using **shadowBlur**, the shadow color by using **shadowColor**, and the shadow offset by using **shadowOffset**. 310 311 312```html 313<!-- xxx.hml --> 314<div class="container"> 315 <canvas ref="canvas1"></canvas> 316 <select @change="change"> 317 <option value="value1">LinearGradient</option> 318 <option value="value2">RadialGradient</option> 319 <option value="value3">shadowBlur</option> 320 <option value="value4">shadowOffset</option> 321 </select> 322</div> 323``` 324 325 326```css 327/* xxx.css */ 328.container{ 329 width: 100%; 330 height: 100%; 331 flex-direction: column; 332 justify-content: center; 333 align-items: center; 334 background-color: #F1F3F5; 335} 336canvas{ 337 width: 600px; 338 height: 500px; 339 background-color: #fdfdfd; 340 border: 5px solid red; 341} 342select{ 343 margin-top: 50px; 344 width: 250px; 345 height: 100px; 346 background-color: white; 347} 348``` 349 350 351```js 352// xxx.js 353export default { 354 data:{ 355 el: null, 356 ctx: null, 357 }, 358 onShow(){ 359 this.el = this.$refs.canvas1; 360 this.ctx = this.el.getContext("2d",{antialias: true}); 361 // Create a linear gradient. 362 let gradient = this.ctx.createLinearGradient(100,100, 400,300); 363 // Add gradient colors. 364 gradient.addColorStop(0.0, 'red'); 365 gradient.addColorStop(0.7, 'white'); 366 gradient.addColorStop(1.0, 'green'); 367 // Apply the gradient. 368 this.ctx.fillStyle = gradient; 369 this.ctx.fillRect(100, 100, 400, 300); 370 }, 371 change(e){ 372 if(e.newValue == 'value1'){ 373 // Clear the contents on the canvas. 374 this.ctx.clearRect(0,0,600,500); 375 let gradient = this.ctx.createLinearGradient(100,100, 400,300); 376 gradient.addColorStop(0.0, 'red'); 377 gradient.addColorStop(0.7, 'white'); 378 gradient.addColorStop(1.0, 'green'); 379 this.ctx.fillStyle = gradient; 380 // Set the level of shadow blur. 381 this.ctx.shadowBlur = 0; 382 // Set the distance that shadows will be offset vertically. 383 this.ctx.shadowOffsetY = 0; 384 // Set the distance that shadows will be offset horizontally. 385 this.ctx.shadowOffsetX = 0; 386 this.ctx.fillRect(100, 100, 400, 300); 387 }else if(e.newValue == 'value2'){ 388 this.ctx.clearRect(0,0,600,500); 389 // Create a radial gradient. 390 let gradient = this.ctx.createRadialGradient(300,250,20,300,250,100); 391 gradient.addColorStop(0.0, 'red'); 392 gradient.addColorStop(0.7, 'white'); 393 gradient.addColorStop(1.0, 'green'); 394 this.ctx.shadowBlur = 0; 395 this.ctx.shadowOffsetY = 0; 396 this.ctx.shadowOffsetX = 0; 397 this.ctx.fillStyle = gradient; 398 this.ctx.fillRect(100, 100, 400, 300); 399 }else if(e.newValue == 'value3'){ 400 this.ctx.clearRect(0,0,600,500); 401 let gradient = this.ctx.createLinearGradient(100,100, 400,400); 402 gradient.addColorStop(0.0, 'red'); 403 gradient.addColorStop(0.5, 'white'); 404 gradient.addColorStop(1, '#17ea35'); 405 // Set the level of shadow blur. 406 this.ctx.shadowBlur = 30; 407 // Set the shadow color. 408 this.ctx.shadowColor = 'rgb(229, 16, 16)'; 409 this.ctx.fillStyle = gradient; 410 this.ctx.fillRect(100, 100, 400, 300); 411 }else if(e.newValue == 'value4'){ 412 this.ctx.clearRect(0,0,600,500); 413 this.ctx.clearRect(0,0,600,500); 414 let gradient = this.ctx.createRadialGradient(300,250,20,300,250,200); 415 gradient.addColorStop(0.0, 'red'); 416 gradient.addColorStop(0.5, 'white'); 417 gradient.addColorStop(1, '#17ea35'); 418 // Set the level of shadow blur. 419 this.ctx.shadowBlur = 30; 420 this.ctx.shadowOffsetY = 30; 421 // Set the shadow color. 422 this.ctx.shadowColor = 'rgb(23, 1, 1)'; 423 this.ctx.fillStyle = gradient; 424 this.ctx.fillRect(100, 100, 400, 300); 425 } 426 }, 427} 428``` 429 430![en-us_image_0000001231683148](figures/en-us_image_0000001231683148.gif) 431 432 433## Filling Texts 434 435Create a text and use the **fillText** method to write the text on the canvas. Use the **globalAlpha** attribute to change the baseline transparency to avoid the text being hidden by the baseline. Then set the **textAlign** and **textBaseline** attributes to determine the text position based on the baseline. 436 437 438```html 439<!-- xxx.hml --> 440<div class="container"> 441 <canvas ref="canvas1"></canvas> 442 <select @change="change"> 443 <option value="value1">text</option> 444 <option value="value2">textBaseline</option> 445 <option value="value3">textAlign</option> 446 </select> 447</div> 448``` 449 450 451```css 452/* xxx.css */ 453.container{ 454 width: 100%; 455 height: 100%; 456 flex-direction: column; 457 justify-content: center; 458 align-items: center; 459 background-color: #F1F3F5; 460} 461canvas{ 462 width: 600px; 463 height: 500px; 464 background-color: #fdfdfd; 465 border: 5px solid red; 466} 467select{ 468 margin-top: 50px; 469 width: 250px; 470 height: 100px; 471 background-color: white; 472} 473``` 474 475 476```js 477// xxx.js 478export default { 479 data:{ 480 el: null, 481 ctx: null, 482 }, 483 onShow(){ 484 this.el = this.$refs.canvas1; 485 this.ctx = this.el.getContext("2d",{antialias: true}); 486 // Create a text. 487 let text = "Hello World"; 488 // Set the font. 489 this.ctx.font = '30px'; 490 this.ctx.fillText("with:"+this.ctx.measureText(text).width, 200, 300); 491 // Set the fill text. 492 this.ctx.fillText(text, 200, 250); 493 }, 494 change(e){ 495 if(e.newValue == 'value1'){ 496 // Clear the contents on the canvas. 497 this.ctx.clearRect(0,0,600,500); 498 // Start a new path. 499 this.ctx.beginPath(); 500 // Initialize the textAlign value. 501 this.ctx.textAlign = 'left'; 502 // Initialize textBaseline. 503 this.ctx.textBaseline = 'alphabetic'; 504 // Set the font. 505 this.ctx.font = '30px'; 506 let text = "Hello World"; 507 // Obtain the font width. 508 this.ctx.fillText("with:"+this.ctx.measureText(text).width, 200, 300); 509 // Set the fill text. 510 this.ctx.fillText(text, 200, 250); 511 }else if(e.newValue == 'value2'){ 512 this.ctx.clearRect(0,0,600,500); 513 this.ctx.beginPath(); 514 // Set the Alpha value. 515 this.ctx.globalAlpha = 0.1; 516 // Set the line width. 517 this.ctx.lineWidth = 10; 518 // Set the line segment color. 519 this.ctx.strokeStyle = '#0000ff'; 520 // Move from the current point to a target position. 521 this.ctx.moveTo(0, 240); 522 // Connect the current point to a target position. 523 this.ctx.lineTo(600, 240); 524 this.ctx.stroke(); 525 this.ctx.font = '35px'; 526 this.ctx.globalAlpha = 1; 527 // Initialize the textAlign value. 528 this.ctx.textAlign = 'left'; 529 // Set textBaseline. 530 this.ctx.textBaseline = 'top'; 531 this.ctx.fillText('Top', 50, 240); 532 this.ctx.textBaseline = 'bottom'; 533 this.ctx.fillText('Bottom', 200, 240); 534 this.ctx.textBaseline = 'middle'; 535 this.ctx.fillText('Middle', 400, 240); 536 }else if(e.newValue == 'value3'){ 537 // Clear the contents on the canvas. 538 this.ctx.clearRect(0,0,600,500); 539 this.ctx.beginPath(); 540 this.ctx.globalAlpha = 0.1; 541 this.ctx.lineWidth = 10; 542 this.ctx.strokeStyle = '#0000ff'; 543 this.ctx.moveTo(300, 0); 544 this.ctx.lineTo(300, 500); 545 this.ctx.stroke(); 546 this.ctx.font = '35px'; 547 this.ctx.globalAlpha = 1; 548 // Initialize textBaseline. 549 this.ctx.textBaseline = 'alphabetic'; 550 // Set textAlign. 551 this.ctx.textAlign = 'left'; 552 this.ctx.fillText('textAlign=left',300, 100); 553 this.ctx.textAlign = 'center'; 554 this.ctx.fillText('textAlign=center',300, 250); 555 this.ctx.textAlign = 'right'; 556 this.ctx.fillText('textAlign=right',300, 400); 557 } 558 } 559} 560``` 561 562![en-us_image_0000001276162745](figures/en-us_image_0000001276162745.gif) 563 564> **NOTE** 565> 566> In the **ltr** layout mode, the value **start** equals **left**. In the **rtl** layout mode, the value **start** equals **right**. 567 568 569## Adding Images 570 571After creating an image object, use the **drawImage** attribute to draw the image and set animation styles such as scaling, translating, and rotating. 572 573 574```html 575<!-- xxx.hml --> 576<div class="container"> 577 <div class="content"> 578 <canvas ref="canvas0"></canvas> 579 <text onclick="change">change</text> 580 <canvas ref="canvas1"></canvas> 581 <text onclick="rotate">rotate</text> 582 <canvas ref="canvas2"></canvas> 583 <text onclick="scale">scale</text> 584 <canvas ref="canvas3"></canvas> 585 <text onclick="translate" style="width: 300px;">translate</text> 586 <canvas ref="canvas4"></canvas> 587 <text onclick="transform" style="width: 300px;">transform</text> 588 <canvas ref="canvas5"></canvas> 589 <text onclick="setTransform" style="width: 300px;">setTransform</text> 590 <canvas ref="canvas6"></canvas> 591 </div> 592</div> 593``` 594 595 596```css 597/* xxx.css */ 598.container{ 599 width: 100%; 600 flex-direction: column; 601 background-color: #F1F3F5; 602 align-items: center; 603} 604canvas{ 605 width: 600px; 606 height: 300px; 607 margin-bottom: 100px; 608 background-color: #fdfdfd; 609 border: 5px solid red; 610} 611.content{ 612 width: 80%; 613 margin-top: 50px; 614 margin-bottom: 50px; 615 display: flex; 616 flex-wrap: wrap; 617 justify-content: space-around; 618} 619text{ 620 font-size: 35px; 621 width: 200px; 622 height: 80px; 623 color: white; 624 border-radius: 20px; 625 text-align: center; 626 background-color: #6060e7; 627 margin-bottom: 30px; 628} 629``` 630 631 632```js 633// xxx.js 634import promptAction from '@ohos.promptAction'; 635export default { 636 data:{ 637 compositeOperation: 'source-over' 638 }, 639 onShow(){ 640 let ctx = this.$refs.canvas0.getContext("2d"); 641 // Create an image object. 642 let img = new Image(); 643 // Set the image path. 644 img.src = 'common/images/2.png'; 645 // Set the image width. 646 img.width= 150; 647 // Set the image height. 648 img.height=150; 649 // Create an image tiling container. 650 var pat = ctx.createPattern(img, 'repeat');ctx.fillStyle = pat; 651 ctx.fillRect(0, 0, 600, 300); 652 }, 653 change(){ 654 // Obtain the brush after the canvas is created. 655 let ctx = this.$refs.canvas1.getContext("2d"); 656 ctx.clearRect(0,0,600,1000); 657 if(this.compositeOperation == "source-over"){ 658 this.compositeOperation = "destination-over"; 659 }else{ 660 this.compositeOperation = "source-over"; 661 } 662 ctx.globalCompositeOperation = this.compositeOperation; 663 let img = new Image(); 664 img.src = 'common/images/2.png'; 665 // Invoked when the image is successfully obtained. 666 img.onload = function() { 667 ctx.drawImage(img, 150, 20, 200, 200); 668 }; 669 let img1 = new Image(); 670 img1.src = 'common/images/3.png'; 671 img1.onload = function() { 672 // Draw an image. 673 ctx.drawImage(img1, 250, 80, 200, 200); 674 }; 675 // A method is triggered when the image fails to be obtained. 676 img1.onerror = function() { 677 promptAction.showToast({message:"error",duration:2000}) 678 }; 679 }, 680 rotate(){ 681 let ctx = this.$refs.canvas2.getContext("2d"); 682 ctx.clearRect(0,0,600,300); 683 // Rotate the image. 684 ctx.rotate(10 * Math.PI / 180); 685 let img = new Image(); 686 img.src = 'common/images/2.png'; 687 img.onload = function() { 688 ctx.drawImage(img, 300, 0, 100, 100); 689 }; 690 }, 691 scale(){ 692 let ctx = this.$refs.canvas3.getContext("2d"); 693 ctx.clearRect(0,0,600,200); 694 // Scale the image. 695 ctx.scale(1.3,1.2); 696 let img = new Image(); 697 img.src = 'common/images/2.png'; 698 img.onload = function() { 699 ctx.drawImage(img, 0, 0, 50, 50); 700 }; 701 }, 702 translate(){ 703 let ctx = this.$refs.canvas4.getContext("2d"); 704 ctx.clearRect(0,0,600,300); 705 ctx.translate(10,0); 706 let img = new Image(); 707 img.src = 'common/images/2.png'; 708 img.onload = function() { 709 ctx.drawImage(img, 0, 50, 300, 200); 710 }; 711 }, 712 transform(){ 713 let ctx = this.$refs.canvas5.getContext("2d"); 714 ctx.clearRect(0,0,600,300); 715 ctx.transform(1.1, 0.1, 0.1, 1, 10, 0); 716 let img = new Image(); 717 img.src = 'common/images/2.png'; 718 img.onload = function() { 719 ctx.drawImage(img, 0, 50, 100, 100); 720 }; 721 }, 722 setTransform(){ 723 let ctx = this.$refs.canvas6.getContext("2d"); 724 ctx.clearRect(0,0,600,300); 725 ctx.setTransform(1.1, 0.1, 0.1, 1, 10, 0); 726 let img = new Image(); 727 img.src = 'common/images/2.png'; 728 img.onload = function() { 729 ctx.drawImage(img, 0, 50, 100, 100); 730 }; 731 }, 732} 733``` 734 735![en-us_image_0000001232003008](figures/en-us_image_0000001232003008.gif) 736 737> **NOTE** 738> - Unlike the **transform()** function, the **setTransform()** function resets the existing transformation matrix and creates a transformation matrix even if it uses the same parameters. 739> 740> - The following formulas calculate coordinates of the transformed graph. **x** and **y** represent coordinates before transformation, and **x'** and **y'** represent coordinates after transformation. 741> x' = scaleX \* x + skewY \* y + translateX 742> 743> y' = skewX \* x + scaleY \* y + translateY 744 745 746## Adding Methods 747 748Use the **save** method to save the brush style, and use the **restore** method to restore the saved settings. In the following example, set the brush to red. After the brush setting is saved, clear the canvas and change the brush to blue. In this moment, directly using the brush will get a blue rectangle; using the brush after the restore operation will get a red rectangle. 749 750 751```html 752<!-- xxx.hml --> 753<div class="container"> 754 <div class="content"> 755 <canvas ref="canvas"></canvas> 756 </div> 757 <div class="content"> 758 <text onclick="save">save</text> 759 <text onclick="clear">clear</text> 760 <text onclick="restore">restore</text> 761 </div> 762</div> 763``` 764 765 766```css 767/* xxx.css */ 768.container{ 769 width: 100%; 770 height: 100%; 771 flex-direction: column; 772 background-color: #F1F3F5; 773 align-items: center; 774} 775canvas{ 776 margin-top: 300px; 777 width: 600px; 778 height: 500px; 779 background-color: #fdfdfd; 780 border: 5px solid red; 781} 782.content{ 783 width: 80%; 784 margin-top: 50px; 785 margin-bottom: 50px; 786 display: flex; 787 flex-wrap: wrap; 788 justify-content: space-around; 789} 790text{ 791 width: 150px; 792 height: 80px; 793 color: white; 794 border-radius: 20px; 795 text-align: center; 796 background-color: #6060e7; 797 margin-bottom: 30px; 798} 799``` 800 801 802```js 803// xxx.js 804import promptAction from '@ohos.promptAction'; 805export default { 806 data:{ 807 ctx: '', 808 }, 809 onShow(){ 810 this.ctx = this.$refs.canvas.getContext("2d"); 811 this.ctx.fillStyle = "red" 812 this.ctx.fillRect(200, 150, 200, 200); 813 }, 814 save(){ 815 // Save the brush setting. 816 this.ctx.save(); 817 promptAction.showToast({message:"save succeed"}); 818 }, 819 clear(){ 820 this.ctx.clearRect(0,0,600,500); 821 // Change the brush color. 822 this.ctx.fillStyle = "#2133d2"; 823 }, 824 restore(){ 825 this.ctx.beginPath(); 826 // Restore the brush setting. 827 this.ctx.restore(); 828 this.ctx.fillRect(200, 150, 200, 200); 829 }, 830} 831``` 832 833![en-us_image_0000001231683144](figures/en-us_image_0000001231683144.gif) 834