• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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![en-us_image_0000001232162320](figures/en-us_image_0000001232162320.gif)
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 **&lt;select&gt;** 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![en-us_image_0000001232003004](figures/en-us_image_0000001232003004.gif)
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![en-us_image_0000001231683148](figures/en-us_image_0000001231683148.gif)
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![en-us_image_0000001276162745](figures/en-us_image_0000001276162745.gif)
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![en-us_image_0000001232003008](figures/en-us_image_0000001232003008.gif)
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![en-us_image_0000001231683144](figures/en-us_image_0000001231683144.gif)
828