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