ALEMÁN
III. RESULTADOS
Canvas provides a set of drawing commands that can be used to build complex graphics. Most of the drawing commands are for building paths. In fact, canvas only includes commands for one shape primitive: the rectangle. You will have to build any other shapes using a combination of simpler curves.
Given a drawing Context, the basic curves are:
• Context.lineTo(x, y): Draws a line from the current pen position to the specified coordinates.
• Context.arc(x, y, radius, startAngle, endAngle, anticlockwise): Draws an arc along a circle centered at (x, y) with the specified radius. The startAngle and endAngle parameters are the start and end angles in radians, and the optional anticlockwise parameter is a boolean indicating whether the curve should be drawn anticlockwise (the default is false, so arcs by default are drawn clockwise).
• Context.quadraticCurveTo(cp1x, cp1y, x, y): Draws a quadratic curve starting at the current pen location and ending at the coordinates (x, y), with the control point at (cp1x, cp1y).
• Context.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y): Draw a bezier curve starting at the current pen location and ending at the coordinates (x, y), with control point 1 specified by (cp1x, cp1y) and control point 2 specified by (cp2x, cp2y).
• Context.rect(x, y, width, height): Draw a rectangle starting at (x, y) with the width and height specified.
Declaring paths is done using two simple commands:
• Context.beginPath(): Starts a new path definition. All curves that follow until the path is closed will be included in the path.
• Context.closePath(): Ends the path definition, and closes the path by drawing a straight line from the current pen position to the starting point of the path.
By themselves, paths are invisible. You have to tell the canvas to either stroke them or fill them:
• Context.strokeStyle: This property defines the style that will be stroked on the current path when the stroke method is called. This property can take any valid CSS color string (e.g., 'red', '#000', or 'rgb(30, 50, 100)'), a gradient object, or a pattern object.
• Context.stroke(): Strokes the current path with the style specified in Context.strokeStyle.
• Context.fillStyle: This property defines the style that will be filled into the current path when the fill method is called. This property can take a CSS color string, a gradient object, or a pattern object.
• Context.fill(): Fills the current path with the style specified in Context.fillStyle.
• Context.lineWidth: This property defines the thickness of the stroke applied to paths. Defaults to 1 unit.
• Context.lineCap: This property defines how lines are capped. Valid values are:
• butt: The line ends are squared off and end precisely at the specified endpoint.
This is the default value.
• round: The line ends are rounded and end slightly over the specified endpoint.
• square: The line ends are squared by adding a box to the end of the line whose width is equal to the width of the line and whose height is half of the width of the line.
• Context.lineJoin: This property defines how connecting lines are joined together.
Valid values are:
• bevel: The joint is beveled.
• miter: The joint is mitered.
• round: The joint is rounded.
Listing 4-4 gives an illustration of the lineCap property.
Listing 4-4. Line Caps
<!DOCTYPE html>
<html>
<head>
<title>The HTML5 Programmer's Reference</title>
<style>
canvas {
border: 1px solid #000;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="200" height="200">Did You Know: Every time you use a browser that doesn't support HTML5, somewhere a kitten cries. Be nice to kittens, upgrade your browser!
</canvas>
<script>
// Get the context we will be using for drawing.
var myCanvas = document.getElementById('myCanvas');
var myContext = myCanvas.getContext('2d');
myContext.lineWidth = 20;
// Set up an array of valid ending types.
var arrEndings = ['round', 'square', 'butt'];
var i = 0, arrEndingsLength = arrEndings.length;
for (i = 0; i < arrEndingsLength; i++){
myContext.lineCap = arrEndings[i];
myContext.beginPath();
myContext.moveTo(50 + (i * 50), 35);
myContext.lineTo(50 + (i * 50), 170);
myContext.stroke();
}
</script>
</body>
</html>
This example uses the canvas to draw thick lines to better illustrate line caps. As always, begin by getting the drawing context of your target canvas, and setting the lineWidth for the drawing. Then make use of an array of line ending values and loop through the array to draw a line for each one, as shown in Figure 4-3.
Figure 4-3. Canvas line caps
You can see that the rounded and squared caps take the line a bit over the actual end of the line.
Sometimes this can cause strange effects if your strokes need to be particularly tight. If that’s the case, just reduce the length of the path a bit to account for the extra stroke.
Listing 4-5 illustrates the various values of the lineJoin property.
Listing 4-5. Line Joins
<!DOCTYPE html>
<html>
<head>
<title>The HTML5 Programmer's Reference</title>
<style>
canvas {
border: 1px solid #000;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="200" height="200">Did You Know: Every time you use a browser that doesn't support HTML5, somewhere a kitten cries. Be nice to kittens, upgrade your browser!
</canvas>
<script>
// Get the context we will be using for drawing.
var myCanvas = document.getElementById('myCanvas');
var myContext = myCanvas.getContext('2d');
myContext.lineWidth = 20;
// Set up an array of valid ending types.
var arrJoins = ['round', 'miter', 'bevel'];
var i = 0, arrJoinsLength = arrJoins.length;
for (i = 0; i < arrJoinsLength; i++){
myContext.lineJoin = arrJoins[i];
myContext.beginPath();
myContext.moveTo(55, 60 + (i * 60));
myContext.lineTo(95, 20 + (i * 60));
myContext.lineTo(135, 60 + (i * 60));
myContext.stroke();
}
</script>
</body>
</html>
Similar to the previous example, Listing 4-5 uses an array of valid join values to provide the structure for this demonstration. It loops through the array and draws an example of each one, as shown in Figure 4-4.
You can see that the round join provides a slightly rounded cap on the obtuse side of the joint, while the miter join slightly squares the obtuse side.
Listing 4-6 shows using the stroke properties on arcs.
Listing 4-6. Random Circle Generator
<!DOCTYPE html>
<html>
<head>
<title>The HTML5 Programmer's Reference</title>
<style>
canvas {
border: 1px solid #000;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="200" height="200">Did You Know: Every time you use a browser that doesn't support HTML5, somewhere a kitten cries. Be nice to kittens, upgrade your browser!
</canvas>
<script>
// Get the context we will be using for drawing.
var myCanvas = document.getElementById('myCanvas');
var myContext = myCanvas.getContext('2d');
// Create a loop that will draw a random circle on the canvas.
var cycles = 10, i = 0;
for (i = 0; i < cycles; i++) {
var randX = getRandomIntegerBetween(50, 150);
var randY = getRandomIntegerBetween(50, 150);
Figure 4-4. Canvas line joins
var randRadius = getRandomIntegerBetween(10, 100);
myContext.beginPath();
myContext.arc(randX, randY, randRadius, 0, 6.3);
randStroke();
} /**
* Returns a random integer between the specified minimum and maximum values.
* @param {number} min The lower boundary for the random number.
* @param {number} max The upper boundary for the random number.
* @return {number}
*/
function getRandomIntegerBetween(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
} /**
* Returns a random color formatted as an rgb string.
* @return {string}
*/
function getRandRGB() {
var randRed = getRandomIntegerBetween(0, 255);
var randGreen = getRandomIntegerBetween(0, 255);
var randBlue = getRandomIntegerBetween(0, 255);
return 'rgb(' + randRed + ', ' + randGreen + ', ' + randBlue + ')';
} /**
* Performs a randomized stroke on the current path.
*/
function randStroke() {
myContext.lineWidth = getRandomIntegerBetween(1, 10);
myContext.strokeStyle = getRandRGB();
myContext.stroke();
}
</script>
</body>
</html>
In this example you are creating ten random circles on the canvas, each at a random location, with a random radius, line width, and stroke color. The getRandomIntegerBetween function makes it easy to get the numbers you need. You also have a randStroke function for stroking the current path with a random width and color. The results are shown in Figure 4-5.
I mentioned before that canvas can also draw rectangles. The commands are simple:
• Context.fillRect(x, y, width, height): Draw a rectangle at the specified coordinates and with the specified width and height filled with the current fill style.
• Context.strokeRect(x, y, width, height): Draw a rectangle at the specified coordinates and with the specified width and height stroked with the current stroke style.
• Context.clearRect(x, y, width, height): Clears the specified rectangular area of any other drawing.
Listing 4-7 illustrates drawing rectangles.
Listing 4-7. Drawing Rectangles in a Canvas
<!DOCTYPE html>
<html>
<head>
<title>The HTML5 Programmer's Reference</title>
<style>
canvas {
border: 1px solid #000;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="200" height="200">Did You Know: Every time you use a browser that doesn't support HTML5, somewhere a kitten cries. Be nice to kittens, upgrade your browser!
</canvas>
<script>
Figure 4-5. The results of Listing 4-6
// Get the context we will be using for drawing.
var myCanvas = document.getElementById('myCanvas');
var myContext = myCanvas.getContext('2d');
// Set a stroke style and stroke a rectangle.
myContext.strokeStyle = 'green';
myContext.strokeRect(30, 30, 50, 100);
// Set a fill style and fill a rectangle.
myContext.fillStyle = 'rgba(200, 100, 75, 0.5)';
myContext.fillRect(20, 20, 50, 50);
// Clear a rectangle.
myContext.clearRect(25, 25, 25, 25);
</script>
</body>
</html>
You’re not doing anything fancy with this example, just stroking, filling, and clearing rectangles.
The results look as you would expect (Figure 4-6).
Figure 4-6. Rectangles—yay!