1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
|
---
title: Dibujando formas con canvas
slug: Web/API/Canvas_API/Tutorial/Drawing_shapes
tags:
- Canvas
- HTML
- HTML Canvas
- HTML5
- Intermedio
- Tutorial
- graficos
translation_of: Web/API/Canvas_API/Tutorial/Drawing_shapes
original_slug: Web/Guide/HTML/Canvas_tutorial/Dibujando_formas
---
<div>{{CanvasSidebar}} {{PreviousNext("Web/API/Canvas_API/Tutorial/Basic_usage", "Web/API/Canvas_API/Tutorial/Applying_styles_and_colors")}}</div>
<div class="summary">
<p>Ahora que hemos preparado nuestro <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_usage">entorno canvas</a>, podemos entrar en detalles de como dibujar en el canvas. Al final de este artículo, habrás aprendido como dibujar rectángulos, triángulos, líneas, arcos y curvas, dándote familiaridad con algunas figuras básicas. Trabajar con rutas es esencial cuando dibujamos objetos sobre el canvas y veremos como se puede hacer eso.</p>
</div>
<h2 id="La_cuadrícula">La cuadrícula</h2>
<p><img alt="" class="internal" src="https://mdn.mozillademos.org/files/224/Canvas_default_grid.png" style="float: right; height: 220px; width: 220px;">Antes de que podamos empezar a dibujar, necesitamos hablar sobre la cuadrícula del canvas o el <strong>espacio de coordenadas</strong>. La plantilla HTML de la página anterior tenía un elemento canvas con un 'height' y un 'width' de 150 píxeles. A la derecha, puedes ver este canvas con la cuadrícula por defecto superpuesta. Normalmente una unidad en la cuadrícula corresponde a un píxel en el elemento canvas. El origen de esta cuadrícula está posicionado en la esquina superior izquierda (coordenada (0,0)). Todos los elementos estan posicionados de manera relativa a este punto, así que la posición de la esquina superior izquierda del cuadrado azul es de 'x' pixeles desde la izquierda y 'y' pixeles desde arriba (coordenada (x,y)). Mas tarde en este tutorial veremos como trasladar el punto de origen a una posicion diferente, girar la cuadrícula e incluso darle una escala diferente. Por ahora nos dedicaremos a lo mas común.</p>
<h2 id="Dibujando_rectángulos">Dibujando rectángulos</h2>
<p>A diferencia de <a href="/en-US/docs/SVG" rel="internal" title="en/SVG">SVG</a>, {{HTMLElement("canvas")}} solo soporta una forma primitiva: rectangulos. Todas las otras formas deben ser creadas por la combinación de uno o más trazos, listas de puntos conectados por líneas. Afortunadamente, tenemos una variedad de funciones para dibujar trazos que hacen posible componer formas muy complejas.</p>
<div id="section_3">
<p>Primero veamos el rectángulo. Aquí hay tres funciones que podemos usar en el canvas para dibujarlos:</p>
<dl>
<dt><code>fillRect(<em>x</em>, <em>y</em>, <em>width</em>, <em>height</em>)</code></dt>
<dd>Dibuja un rectángulo relleno.</dd>
<dt><code>strokeRect(<em>x</em>, <em>y</em>, <em>width</em>, <em>height</em>)</code></dt>
<dd>Dibuja el contorno de un rectángulo.</dd>
<dt><code>clearRect(<em>x</em>, <em>y</em>, <em>width</em>, <em>height</em>)</code></dt>
<dd>Borra un área rectangular especificada, dejándola totalmente transparente.</dd>
</dl>
<p>Cada una de estas tres funciones toma los mismos parámetros. X e Y especifican la posición del canvas (en relación con el origen) desde la esquina superior izquierda del rectángulo. Tambien especifica los parámetros de anchura y altura que proporcionan el tamaño del rectángulo.</p>
<p>A continuación se muestra la función draw() de la página anterior, pero ahora haciendo uso de estas tres funciones.</p>
<h3 id="Ejemplo_de_forma_rectangular">Ejemplo de forma rectangular</h3>
<div class="hidden">
<pre class="brush: html"><html>
<body onload="draw();">
<canvas id="canvas" width="150" height="150"></canvas>
</body>
</html>
</pre>
</div>
<pre class="brush: js">function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.fillRect(25,25,100,100);
ctx.clearRect(45,45,60,60);
ctx.strokeRect(50,50,50,50);
}
}</pre>
<p>El resultado de este ejemplo se muestra a continuación.</p>
<p>{{EmbedLiveSample("Rectangular_shape_example", 160, 160, "https://mdn.mozillademos.org/files/245/Canvas_rect.png")}}</p>
<p>La función fillRect() dibuja un cuadrado grande negro de 100 píxeles en cada lado. La función clearRect() luego borra un cuadrado de 60x60 píxeles del centro, y luego strokeRect() es llamado para crear un contorno rectangular de 50x50 píxeles dentro del cuadrado borrado.</p>
<p>En las próximas páginas veremos dos métodos alternativos para clearRect(), y también veremos cómo cambiar el color y el trazo de diferentes formas.</p>
<p>A diferencia de las funciones de trazo que veremos en la próxima sección, las tres funciones del rectángulo dibujan inmediatamente en el canvas.</p>
<h2 id="Dibujando_trazos">Dibujando trazos</h2>
<p>Crear formas mediante trazos requiere algunos pasos adicionales.</p>
<ol>
<li>Primero, se crea el trazo.</li>
<li>A continuación, se usan <a href="/es/docs/Web/API/CanvasRenderingContext2D#Paths">comandos de dibujo</a> para dibujar dentro del trazo.</li>
<li>Después, se cierra el trazo.</li>
<li>Una vez el trazo ha sido creado, se le puede dar contorno o relleno para renderizarlo.</li>
</ol>
<p>Estas son las funciones que se usan para llevar a cabo estos pasos:</p>
<dl>
<dt><code>beginPath()</code></dt>
<dd>Crea un nuevo trazo. Una vez creado, los comandos de dibujo futuros son aplicados dentro del trazo y usados para construir el nuevo trazo hacia arriba.</dd>
<dt><code>closePath()</code></dt>
<dd>Cierra el trazo de tal forma que los comandos de dibujo futuros son, una vez más redireccionados al contexto.</dd>
<dt><code>stroke()</code></dt>
<dd>Dibuja el contorno de la forma.</dd>
<dt><code>fill()</code></dt>
<dd>Dibuja una forma solida rellenando el área del trazo.</dd>
</dl>
<p>El primer paso para crear un trazo es llamar la función <code>beginPath()</code>. Internamente, los trazos son guardados como una lista de subtrazos (lineas, arcos, etc) los cuales juntos crean una forma. Todo tiempo que sea llamado este método la lista es reseteada y podemos empezar a dibujar nuevas formas.</p>
<div class="note"><strong>Nota:</strong> Cuando el trazo actual este vacio, como aparece inmediatamente despues de llamar la función <code>beginPath()</code>, o en un canvas nuevo, el primer comando para la construcción del trazo es siempre tratada como un <code>moveTo()</code>, independientemente de cual es el trazo actual. Por esta razón casi siempre querrás específicamente setear tu posición de inicio despues de resetear un trazo.</div>
<p>El segundo paso es llamar los métodos que específican los trazos a crear. Los veremos en seguida.</p>
<p>El tercero, y un paso opcional, es llamar a la función <code>closePath()</code>. Este método trata de cerrar la forma dibujando una linea recta desde el punto actual al inicio. Si la forma ya ha sido cerrada o hay solamente un punto en la lista, la función hace nada.</p>
<div class="note"><strong>Nota:</strong> Cuando llamas a la función <code>fill()</code>, cualquier forma abierta es cerrada automaticamente, de tal forma que no tendrás que llamar a la función <code>closePath()</code>. Este no es el caso cuando llamas a la función <code>stroke()</code>.</div>
<h3 id="Dibujando_un_triangulo">Dibujando un triangulo</h3>
<p>Por ejemplo, el código para dibujar un triangulo luciría como el siguiente:</p>
<div class="hidden">
<pre class="brush: html"><html>
<body onload="draw();">
<canvas id="canvas" width="150" height="150"></canvas>
</body>
</html>
</pre>
</div>
<pre class="brush: js">function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(75,50);
ctx.lineTo(100,75);
ctx.lineTo(100,25);
ctx.closePath();
ctx.fill();
}
}
</pre>
<p>El resultado lucirá así:</p>
<p>{{EmbedLiveSample("Drawing_a_triangle", 160, 160)}}</p>
<h3 id="Moviendo_la_pluma">Moviendo la pluma</h3>
<p>Una función muy útil, la cual realmente no dibuja algo pero convierte parte de la lista de trazos descrita arriba, es la función <code>moveTo()</code>. Puedes, probablemente, pensar mejor de esta como levantar el lápiz o la pluma de un punto en un pedazo de papel y ponerlo en el siguiente punto.</p>
<dl>
<dt><code>moveTo(<em>x</em>, <em>y</em>)</code></dt>
<dd>Mueve la pluma a las coordenadas específicadas por <code>x</code> e <code>y</code>.</dd>
</dl>
<p>Cuando el canvas es inicializado ó la función <code>beginPath()</code> es llamada, querrás usar la función <code>moveTo()</code> para colocar el punto de inicio en alguna otra parte. Podríamos usar <code>moveTo()</code> para dibujar trazos sin conectar. Toma un vistazo a la cara sonriente de abajo. He marcado los lugares donde use el método <code>moveTo()</code> (las líneas rojas).</p>
<p>Para intentar esto por tí mismo, puedes usar el pequeño código de abajo. Solo pégalo dentro de la función <code>draw()</code> que vimos antes.</p>
<div class="hidden">
<pre class="brush: html"><html>
<body onload="draw();">
<canvas id="canvas" width="150" height="150"></canvas>
</body>
</html>
</pre>
</div>
<pre class="brush: js">function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.arc(75,75,50,0,Math.PI*2,true); // Círculo externo
ctx.moveTo(110,75);
ctx.arc(75,75,35,0,Math.PI,false); // Boca (contra reloj)
ctx.moveTo(65,65);
ctx.arc(60,65,5,0,Math.PI*2,true); // Ojo izquierdo
ctx.moveTo(95,65);
ctx.arc(90,65,5,0,Math.PI*2,true); // Ojo derecho
ctx.stroke();
}
}
</pre>
<p>El resultado luce así:</p>
<p>{{EmbedLiveSample("Moving_the_pen", 160, 160, "https://mdn.mozillademos.org/files/252/Canvas_smiley.png")}}</p>
<p>Si quisieras ver las líneas conectadas, puedes remover las líneas de código que llaman <code>moveTo()</code>.</p>
<div class="note">
<p><strong>Nota:</strong> Para aprender más sobre la función <code>arc()</code>, vea los {{anch("Arcs")}} a continuación.</p>
</div>
<h3 id="Líneas">Líneas</h3>
<p>Para dibujar lineas rectas usa el método <code>lineTo()</code>.</p>
<dl>
<dt><code>lineTo(<em>x</em>, <em>y</em>)</code></dt>
<dd>Dibuja una línea desde la posición actual del dibujo a la posición específicada por <code>x</code> e <code>y</code>.</dd>
</dl>
<p>Este método toma dos argumentos <code>x</code> e <code>y</code>, los cuales son las coordenadas del punto final de la linea. El punto de inicio es dependiente de los trazos previamente dibujados, donde el punto final del trazo anterior es el punto inicial para el siguiente, etc. El punto de inicio también puede ser cambiado usando el método <code>moveTo()</code>.</p>
<p>El ejemplo siguiente dibuja dos triángulos, uno rellenado y el otro contorneado.</p>
<div class="hidden">
<pre class="brush: html"><html>
<body onload="draw();">
<canvas id="canvas" width="150" height="150"></canvas>
</body>
</html>
</pre>
</div>
<pre class="brush: js">function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
// Triángulo rellenado
ctx.beginPath();
ctx.moveTo(25,25);
ctx.lineTo(105,25);
ctx.lineTo(25,105);
ctx.fill();
// Triángulo contorneado
ctx.beginPath();
ctx.moveTo(125,125);
ctx.lineTo(125,45);
ctx.lineTo(45,125);
ctx.closePath();
ctx.stroke();
}
}
</pre>
<p>Esto comienza llamando a <code>beginPath()</code> para empezar una nueva forma. Entonces usamos el método <code>moveTo()</code> para mover el punto de inicio a la posición deseada. Debajo de esto dos líneas son dibujadas lo cual pinta dos lados del triángulo.</p>
<p>{{EmbedLiveSample("Lines", 160, 160, "https://mdn.mozillademos.org/files/238/Canvas_lineTo.png")}}</p>
<p>Te darás cuenta de la diferencia entre el triángulo rellenado y el contorneado. Esto es, como se menciona arriba, porque las formas son automáticamente cerradas cuando un trazo es rellenado, pero no cuando esta contorneado. Si sacamos el <code>closePath()</code> para el triángulo contorneado, solamente dos líneas serian dibujadas, no un triángulo completo.</p>
<h3 id="Arcos">Arcos</h3>
<p>Para dibujar arcos o circulos usamos el método <code>arc()</code>. También puedes usar <code>arcTo()</code>, pero su implementación es un poco menos confiable, así que no lo cubriremos aquí.</p>
<dl>
<dt><code>arc(<em>x</em>, <em>y</em>, <em>radius</em>, <em>startAngle</em>, <em>endAngle</em>, <em>anticlockwise</em>)</code></dt>
<dd>Dibuja un arco.</dd>
</dl>
<p>Este método toma cinco parámetros: <code>x</code> e <code>y</code> son las coordenadas del centro del círculo en el cual el arco debería ser dibujado. <code>radius</code> se explica por sí solo. Los parámetros <code>startAngle</code> y <code>endAngle</code> definen el punto de inicio y punto final del arco en radianes a lo largo de la curva del círculo. Estos son medidos desde el eje x. El parámetro <code>anticlockwise</code> es un valor Booleano el cual cuando es verdadero (<code>true</code>) dibuja el arco al contrario de las manecillas del reloj, de lo contrario el arco es dibujado al sentido de las manecillas del reloj.</p>
<div class="note">
<p><strong>Nota</strong>: Los ángulos en la función del arco (<code>arc</code>) son medidos en radianes, no en grados. Para convertir grados a radianes puedes usar la siguiente expresión en Javascript: <code>radians = (Math.PI/180)*degrees</code>.</p>
</div>
<p>El siguiente ejemplo es un poco más complejo que otros que hemos visto arriba. Esto dibuja 12 diferentes arcos, todos con diferentes ángulos y rellenos.</p>
<p>Las dos sentencias <code>for</code> son para iterar a través de las filas y columnas de los arcos. Para cada arco, empezamos un nuevo trazo llamando <code>beginPath()</code>. En el código, cada uno de los parámetros para el arco estan en una variable para su entendimiento, pero no es necesario esto en la vida real.</p>
<p>Las coordenadas <code>x</code> e <code>y</code> deberían ser suficientemente claras. <code>radius</code> y <code>startAngle</code> estan arreglados. El <code>endAngle</code> inicia en 180 grados (la mitad de un círculo) en la primera columna y es incrementado por pasos de 90 grados, culminando en un círculo completo en la última columna.</p>
<p>El parámetro <code>clockwise</code> resulta, en la primera y tercera fila siendo dibujado como un arco al sentido de las manecillas de reloj y la segunda y cuarta fila como arcos al contrario de las manecillas de reloj. Finalmente, la estructura <code>if</code> hace los arcos contorneados a la mitad desde arriba y los arcos hacia abajorellenados a la mitad.</p>
<div class="hidden">
<pre class="brush: html"><html>
<body onload="draw();">
<canvas id="canvas" width="150" height="200"></canvas>
</body>
</html>
</pre>
</div>
<pre class="brush: js">function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
for(var i=0;i<4;i++){
for(var j=0;j<3;j++){
ctx.beginPath();
var x = 25+j*50; // Coordenada x
var y = 25+i*50; // Coordenada y
var radius = 20; // Radio del arco
var startAngle = 0; // Punto inicial del círculo
var endAngle = Math.PI+(Math.PI*j)/2; // Punto final del círculo
var anticlockwise = i%2==0 ? false : true; // Sentido de las manecillas del reloj y contrario a ellas
ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);
if (i>1){
ctx.fill();
} else {
ctx.stroke();
}
}
}
}
}
</pre>
{{EmbedLiveSample("Arcs", 160, 210, "https://mdn.mozillademos.org/files/204/Canvas_arc.png")}}
<h3 id="Curvas_Bezier_curvas_cuadráticas">Curvas Bezier curvas cuadráticas</h3>
<p>El siguiente tipo de trazos disponibles son las <a class="external" href="http://en.wikipedia.org/wiki/B%C3%A9zier_curve" rel="external">curvas Bézier</a>, en sus dos variantes, cúbicas y cuadráticas. Son usadas generalmente para dibujar complejas formas orgánicas.</p>
<dl>
<dt><code>quadraticCurveTo(cp1x, cp1y, x, y)</code></dt>
<dd><span id="result_box" lang="es"><span>Dibuja una curva cuadrática de Bézier desde la posición actual de la pluma hasta el punto final especificado por <code>x</code> e <code>y</code>, utilizando el punto de control especificado por <code>cp1x</code> y <code>cp1y</code>.</span></span></dd>
<dt><code>bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)</code></dt>
<dd>Dibuja una curva cúbica de Bézier desde la posición actual de la pluma hasta el punto final especificado por <code>x</code> e <code>y</code>, utilizando los puntos de control especificados por (<code>cp1x</code>, <code>cp1y</code>) y (<code>cp2x</code>, <code>cp2y</code>).</dd>
</dl>
<p><img alt="" class="internal" src="https://mdn.mozillademos.org/files/223/Canvas_curves.png" style="float: right; height: 190px; width: 190px;">La diferencia entre estos puede describirse mejor utilizando la imagen de la derecha. Una curva cuadrática de Bézier tiene un punto inicial y un punto final (puntos azules) y un solo <strong>punto de control</strong> (indicado por el punto rojo), mientras que una curva cúbica de Bézier utiliza dos puntos de control.</p>
<p>Los parámetros <code>x</code> e <code>y</code> de ambos métodos son las coordenadas del punto final. <code>cp1x</code> y <code>cp1y</code> son las coordenadas del primer punto de control, y <code>cp2x</code> y <code>cp2y</code> son las coordenadas del segundo punto de control.</p>
<p>El uso de curvas cuadráticas y cúbicas Bézier puede ser bastante difícil, ya que a diferencia del software de dibujo vectorial como Adobe Illustrator, no tenemos respuesta visual directa en cuanto a lo que estamos haciendo. Esto hace bastante difícil dibujar formas complejas. En el siguiente ejemplo, vamos a dibujar algunas formas orgánicas simples, pero si tienes el tiempo y, sobre todo, la paciencia, se pueden crear formas mucho más complejas.</p>
<p>No hay nada muy difícil en estos ejemplos. En ambos casos vemos una sucesión de curvas que se dibujan que finalmente dan lugar a una forma completa.</p>
<h4 id="Curvas_de_Bezier_cuadraticas">Curvas de Bezier cuadraticas</h4>
<p>Este ejemplo usa multiples curvas cuadraticas de Bézier para renderizar un globo de voz.</p>
<div class="hidden">
<pre class="brush: html"><html>
<body onload="draw();">
<canvas id="canvas" width="150" height="150"></canvas>
</body>
</html>
</pre>
</div>
<pre class="brush: js">function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
// Quadratric curves example
ctx.beginPath();
ctx.moveTo(75,25);
ctx.quadraticCurveTo(25,25,25,62.5);
ctx.quadraticCurveTo(25,100,50,100);
ctx.quadraticCurveTo(50,120,30,125);
ctx.quadraticCurveTo(60,120,65,100);
ctx.quadraticCurveTo(125,100,125,62.5);
ctx.quadraticCurveTo(125,25,75,25);
ctx.stroke();
}
}
</pre>
<p>{{EmbedLiveSample("Quadratic_Bezier_curves", 160, 160, "https://mdn.mozillademos.org/files/243/Canvas_quadratic.png")}}</p>
<h4 id="Curvas_cúbicas_Bezier">Curvas cúbicas Bezier</h4>
<p>Este ejemplo dibuja un corazon usanco curvas cúbicas de Bézier.</p>
<div class="hidden">
<pre class="brush: html"><html>
<body onload="draw();">
<canvas id="canvas" width="150" height="150"></canvas>
</body>
</html>
</pre>
</div>
<pre class="brush: js">function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
// Quadratric curves example
ctx.beginPath();
ctx.moveTo(75,40);
ctx.bezierCurveTo(75,37,70,25,50,25);
ctx.bezierCurveTo(20,25,20,62.5,20,62.5);
ctx.bezierCurveTo(20,80,40,102,75,120);
ctx.bezierCurveTo(110,102,130,80,130,62.5);
ctx.bezierCurveTo(130,62.5,130,25,100,25);
ctx.bezierCurveTo(85,25,75,37,75,40);
ctx.fill();
}
}
</pre>
<p>{{EmbedLiveSample("Cubic_Bezier_curves", 160, 160, "https://mdn.mozillademos.org/files/207/Canvas_bezier.png")}}</p>
<h3 id="Rectangles">Rectangles</h3>
<p>In addition to the three methods we saw in {{anch("Drawing rectangles")}}, which draw rectangular shapes directly to the canvas, there's also the <code>rect()</code> method, which adds a rectangular path to a currently open path.</p>
<dl>
<dt><code>rect(<em>x</em>, <em>y</em>, <em>width</em>, <em>height</em>)</code></dt>
<dd>Draws a rectangle whose top-left corner is specified by (<code>x</code>, <code>y</code>) with the specified <code>width</code> and <code>height</code>.</dd>
</dl>
<p>When this method is executed, the <code>moveTo()</code> method is automatically called with the parameters (0,0). In other words, the current pen position is automatically reset to the default coordinates.</p>
<h3 id="Making_combinations">Making combinations</h3>
<p>So far, each example on this page has used only one type of path function per shape. However, there's no limitation to the number or types of paths you can use to create a shape. So in this final example, let's combine all of the path functions to make a set of very famous game characters.</p>
<div class="hidden">
<pre class="brush: html"><html>
<body onload="draw();">
<canvas id="canvas" width="150" height="150"></canvas>
</body>
</html>
</pre>
</div>
<pre class="brush: js">function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
roundedRect(ctx,12,12,150,150,15);
roundedRect(ctx,19,19,150,150,9);
roundedRect(ctx,53,53,49,33,10);
roundedRect(ctx,53,119,49,16,6);
roundedRect(ctx,135,53,49,33,10);
roundedRect(ctx,135,119,25,49,10);
ctx.beginPath();
ctx.arc(37,37,13,Math.PI/7,-Math.PI/7,false);
ctx.lineTo(31,37);
ctx.fill();
for(var i=0;i<8;i++){
ctx.fillRect(51+i*16,35,4,4);
}
for(i=0;i<6;i++){
ctx.fillRect(115,51+i*16,4,4);
}
for(i=0;i<8;i++){
ctx.fillRect(51+i*16,99,4,4);
}
ctx.beginPath();
ctx.moveTo(83,116);
ctx.lineTo(83,102);
ctx.bezierCurveTo(83,94,89,88,97,88);
ctx.bezierCurveTo(105,88,111,94,111,102);
ctx.lineTo(111,116);
ctx.lineTo(106.333,111.333);
ctx.lineTo(101.666,116);
ctx.lineTo(97,111.333);
ctx.lineTo(92.333,116);
ctx.lineTo(87.666,111.333);
ctx.lineTo(83,116);
ctx.fill();
ctx.fillStyle = "white";
ctx.beginPath();
ctx.moveTo(91,96);
ctx.bezierCurveTo(88,96,87,99,87,101);
ctx.bezierCurveTo(87,103,88,106,91,106);
ctx.bezierCurveTo(94,106,95,103,95,101);
ctx.bezierCurveTo(95,99,94,96,91,96);
ctx.moveTo(103,96);
ctx.bezierCurveTo(100,96,99,99,99,101);
ctx.bezierCurveTo(99,103,100,106,103,106);
ctx.bezierCurveTo(106,106,107,103,107,101);
ctx.bezierCurveTo(107,99,106,96,103,96);
ctx.fill();
ctx.fillStyle = "black";
ctx.beginPath();
ctx.arc(101,102,2,0,Math.PI*2,true);
ctx.fill();
ctx.beginPath();
ctx.arc(89,102,2,0,Math.PI*2,true);
ctx.fill();
}
}
// A utility function to draw a rectangle with rounded corners.
function roundedRect(ctx,x,y,width,height,radius){
ctx.beginPath();
ctx.moveTo(x,y+radius);
ctx.lineTo(x,y+height-radius);
ctx.quadraticCurveTo(x,y+height,x+radius,y+height);
ctx.lineTo(x+width-radius,y+height);
ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);
ctx.lineTo(x+width,y+radius);
ctx.quadraticCurveTo(x+width,y,x+width-radius,y);
ctx.lineTo(x+radius,y);
ctx.quadraticCurveTo(x,y,x,y+radius);
ctx.stroke();
}
</pre>
<div id="section_18">
<p>The resulting image looks like this:</p>
<p>{{EmbedLiveSample("Making_combinations", 160, 160)}}</p>
<p>We won't go over this in detail, since it's actually surprisingly simple. The most important things to note are the use of the <code>fillStyle</code> property on the drawing context, and the use of a utility function (in this case <code>roundedRect()</code>). Using utility functions for bits of drawing you do often can be very helpful and reduce the amount of code you need, as well as its complexity.</p>
<p>We'll take another look at <code>fillStyle</code>, in more detail, later in this tutorial. Here, all we're doing is using it to change the fill color for paths from the default color of black to white, and then back again.</p>
<p>{{PreviousNext("Web/Guide/HTML/Canvas_tutorial/Basic_usage", "Web/Guide/HTML/Canvas_tutorial/Using_images")}}</p>
</div>
</div>
<p> </p>
|