Draw a Circle Using Triangle
Cartoon shapes with canvas
- « Previous
- Next »
Now that nosotros have gear up upwards our canvas surroundings, we can get into the details of how to draw on the canvas. Past the finish of this article, you lot will take learned how to draw rectangles, triangles, lines, arcs and curves, providing familiarity with some of the bones shapes. Working with paths is essential when drawing objects onto the sail and we will run into how that can be done.
The grid
Before we can first drawing, we demand to talk about the canvas grid or coordinate space. Our HTML skeleton from the previous page had a canvas element 150 pixels broad and 150 pixels high.
Normally 1 unit of measurement in the grid corresponds to i pixel on the canvas. The origin of this grid is positioned in the meridian left corner at coordinate (0,0). All elements are placed relative to this origin. So the position of the pinnacle left corner of the blueish square becomes x pixels from the left and y pixels from the peak, at coordinate (x,y). Later in this tutorial we'll see how we can interpret the origin to a different position, rotate the grid and even scale it, but for now nosotros'll stick to the default.
Cartoon rectangles
Unlike SVG, <sail>
only supports two primitive shapes: rectangles and paths (lists of points connected by lines). All other shapes must be created by combining one or more than paths. Luckily, we take an array of path cartoon functions which brand it possible to compose very complex shapes.
Kickoff let's look at the rectangle. There are three functions that depict rectangles on the canvas:
-
fillRect(10, y, width, top)
-
Draws a filled rectangle.
-
strokeRect(x, y, width, height)
-
Draws a rectangular outline.
-
clearRect(ten, y, width, peak)
-
Clears the specified rectangular expanse, making it fully transparent.
Each of these three functions takes the aforementioned parameters. x
and y
specify the position on the canvass (relative to the origin) of the top-left corner of the rectangle. width
and height
provide the rectangle'due south size.
Below is the draw()
function from the previous page, just at present information technology is making use of these three functions.
Rectangular shape case
function draw ( ) { var canvas = certificate. getElementById ( 'sheet' ) ; if (canvas.getContext) { var ctx = sail. getContext ( '2nd' ) ; ctx. fillRect ( 25 , 25 , 100 , 100 ) ; ctx. clearRect ( 45 , 45 , 60 , 60 ) ; ctx. strokeRect ( 50 , 50 , 50 , 50 ) ; } }
This instance'due south output is shown beneath.
The fillRect()
office draws a large black square 100 pixels on each side. The clearRect()
function so erases a 60x60 pixel square from the center, and so strokeRect()
is chosen to create a rectangular outline 50x50 pixels within the cleared square.
In upcoming pages nosotros'll run across 2 alternative methods for clearRect()
, and we'll too run into how to change the color and stroke mode of the rendered shapes.
Unlike the path functions we'll see in the adjacent section, all three rectangle functions draw immediately to the sheet.
Drawing paths
Now let's look at paths. A path is a list of points, connected past segments of lines that can exist of unlike shapes, curved or not, of different width and of different color. A path, or even a subpath, can exist closed. To make shapes using paths, we take some extra steps:
- Kickoff, yous create the path.
- Then y'all use drawing commands to draw into the path.
- Once the path has been created, you can stroke or make full the path to render it.
Here are the functions used to perform these steps:
-
beginPath()
-
Creates a new path. Once created, futurity drawing commands are directed into the path and used to build the path up.
- Path methods
-
Methods to set unlike paths for objects.
-
closePath()
-
Adds a directly line to the path, going to the start of the current sub-path.
-
stroke()
-
Draws the shape by stroking its outline.
-
fill()
-
Draws a solid shape by filling the path's content area.
The start step to create a path is to call the beginPath()
. Internally, paths are stored as a list of sub-paths (lines, arcs, etc) which together course a shape. Every time this method is called, the list is reset and nosotros can start drawing new shapes.
Note: When the electric current path is empty, such as immediately after calling beginPath()
, or on a newly created canvass, the first path construction command is e'er treated as a moveTo()
, regardless of what it actually is. For that reason, you will almost e'er want to specifically prepare your starting position later resetting a path.
The 2d step is calling the methods that actually specify the paths to be drawn. We'll encounter these shortly.
The third, and an optional step, is to call closePath()
. This method tries to close the shape by cartoon a straight line from the current betoken to the beginning. If the shape has already been closed or at that place's only one point in the list, this function does nothing.
Notation: When you call fill()
, whatever open up shapes are closed automatically, and then you don't have to phone call closePath()
. This is not the instance when you call stroke()
.
Drawing a triangle
For instance, the code for drawing a triangle would await something similar this:
office draw ( ) { var canvas = document. getElementById ( 'sail' ) ; if (sail.getContext) { var ctx = canvas. getContext ( '2d' ) ; ctx. beginPath ( ) ; ctx. moveTo ( 75 , 50 ) ; ctx. lineTo ( 100 , 75 ) ; ctx. lineTo ( 100 , 25 ) ; ctx. fill up ( ) ; } }
The issue looks like this:
Moving the pen
Ane very useful function, which doesn't actually draw anything just becomes part of the path listing described above, is the moveTo()
function. You lot can probably best remember of this as lifting a pen or pencil from one spot on a piece of paper and placing it on the next.
-
moveTo(x, y)
-
Moves the pen to the coordinates specified past
x
andy
.
When the canvas is initialized or beginPath()
is called, you lot typically will want to use the moveTo()
function to place the starting point somewhere else. We could as well utilize moveTo()
to describe unconnected paths. Take a look at the smiley face below.
To try this for yourself, yous can utilize the lawmaking snippet beneath. Merely paste it into the depict()
function we saw earlier.
function depict ( ) { var canvas = document. getElementById ( 'canvas' ) ; if (canvas.getContext) { var ctx = canvas. getContext ( '2nd' ) ; ctx. beginPath ( ) ; ctx. arc ( 75 , 75 , 50 , 0 , Math. PI * 2 , true ) ; // Outer circle ctx. moveTo ( 110 , 75 ) ; ctx. arc ( 75 , 75 , 35 , 0 , Math. PI , false ) ; // Oral fissure (clockwise) ctx. moveTo ( 65 , 65 ) ; ctx. arc ( 60 , 65 , 5 , 0 , Math. PI * 2 , truthful ) ; // Left middle ctx. moveTo ( 95 , 65 ) ; ctx. arc ( 90 , 65 , 5 , 0 , Math. PI * 2 , true ) ; // Right eye ctx. stroke ( ) ; } }
The effect looks like this:
If you'd similar to see the connecting lines, you can remove the lines that call moveTo()
.
Notation: To learn more well-nigh the arc()
role, run across the Arcs section below.
Lines
For cartoon directly lines, utilise the lineTo()
method.
-
lineTo(x, y)
-
Draws a line from the current drawing position to the position specified by
x
andy
.
This method takes two arguments, 10
and y
, which are the coordinates of the line's end point. The starting point is dependent on previously drawn paths, where the terminate point of the previous path is the starting point for the following, etc. The starting point can also be inverse by using the moveTo()
method.
The example below draws ii triangles, i filled and i outlined.
part describe ( ) { var canvas = document. getElementById ( 'canvas' ) ; if (sheet.getContext) { var ctx = canvas. getContext ( '2d' ) ; // Filled triangle ctx. beginPath ( ) ; ctx. moveTo ( 25 , 25 ) ; ctx. lineTo ( 105 , 25 ) ; ctx. lineTo ( 25 , 105 ) ; ctx. fill ( ) ; // Stroked triangle ctx. beginPath ( ) ; ctx. moveTo ( 125 , 125 ) ; ctx. lineTo ( 125 , 45 ) ; ctx. lineTo ( 45 , 125 ) ; ctx. closePath ( ) ; ctx. stroke ( ) ; } }
This starts by calling beginPath()
to commencement a new shape path. We then use the moveTo()
method to motility the starting signal to the desired position. Below this, two lines are drawn which make up 2 sides of the triangle.
You'll find the difference between the filled and stroked triangle. This is, as mentioned above, because shapes are automatically airtight when a path is filled, simply not when they are stroked. If nosotros left out the closePath()
for the stroked triangle, only 2 lines would have been drawn, not a complete triangle.
Arcs
To describe arcs or circles, we use the arc()
or arcTo()
methods.
-
arc(10, y, radius, startAngle, endAngle, counterclockwise)
-
Draws an arc which is centered at (ten, y) position with radius r starting at startAngle and ending at endAngle going in the given direction indicated past counterclockwise (defaulting to clockwise).
-
arcTo(x1, y1, x2, y2, radius)
-
Draws an arc with the given control points and radius, connected to the previous betoken by a straight line.
Let's take a more detailed look at the arc
method, which takes 6 parameters: x
and y
are the coordinates of the center of the circle on which the arc should be drawn. radius
is self-explanatory. The startAngle
and endAngle
parameters define the start and end points of the arc in radians, forth the curve of the circle. These are measured from the x axis. The counterclockwise
parameter is a Boolean value which, when true
, draws the arc counterclockwise; otherwise, the arc is drawn clockwise.
Note: Angles in the arc
function are measured in radians, not degrees. To convert degrees to radians yous tin can use the following JavaScript expression: radians = (Math.PI/180)*degrees
.
The following example is a little more complex than the ones nosotros've seen above. It draws 12 different arcs all with unlike angles and fills.
The two for
loops are for looping through the rows and columns of arcs. For each arc, nosotros start a new path by calling beginPath()
. In the code, each of the parameters for the arc is in a variable for clarity, but you lot wouldn't necessarily practise that in real life.
The x
and y
coordinates should be clear enough. radius
and startAngle
are fixed. The endAngle
starts at 180 degrees (one-half a circumvolve) in the first column and is increased past steps of 90 degrees, culminating in a complete circle in the last column.
The statement for the clockwise
parameter results in the first and third row being drawn equally clockwise arcs and the 2nd and fourth row as counterclockwise arcs. Finally, the if
statement makes the elevation one-half stroked arcs and the lesser half filled arcs.
Note: This example requires a slightly larger canvass than the others on this page: 150 ten 200 pixels.
function draw ( ) { var canvass = document. getElementById ( 'canvas' ) ; if (sheet.getContext) { var ctx = canvas. getContext ( '2nd' ) ; for ( var i = 0 ; i < 4 ; i++ ) { for ( var j = 0 ; j < 3 ; j++ ) { ctx. beginPath ( ) ; var x = 25 + j * 50 ; // x coordinate var y = 25 + i * 50 ; // y coordinate var radius = twenty ; // Arc radius var startAngle = 0 ; // Starting bespeak on circle var endAngle = Math. PI + (Math. PI * j) / two ; // End point on circumvolve var counterclockwise = i % two !== 0 ; // clockwise or counterclockwise ctx. arc (x, y, radius, startAngle, endAngle, counterclockwise) ; if (i > 1 ) { ctx. fill ( ) ; } else { ctx. stroke ( ) ; } } } } }
Bezier and quadratic curves
The side by side blazon of paths available are Bézier curves, available in both cubic and quadratic varieties. These are mostly used to draw circuitous organic shapes.
-
quadraticCurveTo(cp1x, cp1y, ten, y)
-
Draws a quadratic Bézier curve from the electric current pen position to the cease bespeak specified past
x
andy
, using the control point specified pastcp1x
andcp1y
. -
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, ten, y)
-
Draws a cubic Bézier curve from the electric current pen position to the end bespeak specified by
x
andy
, using the command points specified by (cp1x
,cp1y
) and (cp2x, cp2y).
The difference between these is that a quadratic Bézier bend has a get-go and an end betoken (bluish dots) and just one control point (indicated past the red dot) while a cubic Bézier bend uses 2 control points.
The x
and y
parameters in both of these methods are the coordinates of the end point. cp1x
and cp1y
are the coordinates of the starting time control point, and cp2x
and cp2y
are the coordinates of the 2nd control point.
Using quadratic and cubic Bézier curves can be quite challenging, because dissimilar vector cartoon software like Adobe Illustrator, nosotros don't accept straight visual feedback as to what nosotros're doing. This makes it pretty difficult to describe complex shapes. In the following example, we'll be drawing some simple organic shapes, just if you have the time and, almost of all, the patience, much more than complex shapes can be created.
There's nothing very hard in these examples. In both cases we see a succession of curves being drawn which finally event in a complete shape.
Quadratic Bezier curves
This example uses multiple quadratic Bézier curves to return a speech balloon.
function draw ( ) { var canvas = document. getElementById ( 'canvas' ) ; if (sail.getContext) { var ctx = canvas. getContext ( '2nd' ) ; // Quadratic curves case 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 ( ) ; } }
Cubic Bezier curves
This instance draws a middle using cubic Bézier curves.
function draw ( ) { var canvas = document. getElementById ( 'canvass' ) ; if (canvas.getContext) { var ctx = sail. getContext ( '2d' ) ; // Cubic curves example ctx. beginPath ( ) ; ctx. moveTo ( 75 , 40 ) ; ctx. bezierCurveTo ( 75 , 37 , lxx , 25 , 50 , 25 ) ; ctx. bezierCurveTo ( 20 , 25 , twenty , 62.5 , 20 , 62.v ) ; ctx. bezierCurveTo ( xx , fourscore , 40 , 102 , 75 , 120 ) ; ctx. bezierCurveTo ( 110 , 102 , 130 , 80 , 130 , 62.v ) ; ctx. bezierCurveTo ( 130 , 62.v , 130 , 25 , 100 , 25 ) ; ctx. bezierCurveTo ( 85 , 25 , 75 , 37 , 75 , 40 ) ; ctx. fill ( ) ; } }
Rectangles
In addition to the iii methods nosotros saw in Cartoon rectangles, which draw rectangular shapes directly to the sail, there's also the rect()
method, which adds a rectangular path to a currently open path.
-
rect(x, y, width, top)
-
Draws a rectangle whose top-left corner is specified by (
x
,y
) with the specifiedwidth
andsummit
.
Earlier this method is executed, the moveTo()
method is automatically called with the parameters (x,y). In other words, the current pen position is automatically reset to the default coordinates.
Making combinations
Then far, each instance on this folio has used simply one blazon of path office per shape. However, there's no limitation to the number or types of paths you can employ to create a shape. So in this final case, allow's combine all of the path functions to make a ready of very famous game characters.
function draw ( ) { var sail = document. getElementById ( 'sheet' ) ; if (canvass.getContext) { var ctx = canvas. getContext ( '2d' ) ; roundedRect (ctx, 12 , 12 , 150 , 150 , fifteen ) ; roundedRect (ctx, 19 , xix , 150 , 150 , ix ) ; roundedRect (ctx, 53 , 53 , 49 , 33 , 10 ) ; roundedRect (ctx, 53 , 119 , 49 , xvi , 6 ) ; roundedRect (ctx, 135 , 53 , 49 , 33 , x ) ; roundedRect (ctx, 135 , 119 , 25 , 49 , 10 ) ; ctx. beginPath ( ) ; ctx. arc ( 37 , 37 , 13 , Math. PI / 7 , -Math. PI / seven , 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 * sixteen , iv , 4 ) ; } for (i = 0 ; i < viii ; 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 , ii , 0 , Math. PI * two , truthful ) ; ctx. fill up ( ) ; ctx. beginPath ( ) ; ctx. arc ( 89 , 102 , 2 , 0 , Math. PI * 2 , true ) ; ctx. fill up ( ) ; } } // A utility office to draw a rectangle with rounded corners. role roundedRect ( ctx, ten, y, width, height, radius ) { ctx. beginPath ( ) ; ctx. moveTo (x, y + radius) ; ctx. arcTo (x, y + height, x + radius, y + height, radius) ; ctx. arcTo (x + width, y + pinnacle, x + width, y + meridian - radius, radius) ; ctx. arcTo (x + width, y, x + width - radius, y, radius) ; ctx. arcTo (x, y, x, y + radius, radius) ; ctx. stroke ( ) ; }
The resulting prototype looks similar this:
We won't go over this in detail, since it's actually surprisingly elementary. The most important things to annotation are the use of the fillStyle
property on the drawing context, and the use of a utility function (in this instance roundedRect()
). Using utility functions for bits of drawing you do ofttimes can be very helpful and reduce the corporeality of lawmaking yous need, as well as its complexity.
Nosotros'll have some other expect at fillStyle
, in more detail, afterward in this tutorial. Hither, all we're doing is using it to change the make full colour for paths from the default colour of black to white, then dorsum again.
Path2D objects
As we have seen in the last case, there tin can exist a series of paths and cartoon commands to depict objects onto your sail. To simplify the code and to improve performance, the Path2D
object, available in recent versions of browsers, lets you cache or record these drawing commands. You lot are able to play dorsum your paths quickly. Let's encounter how we can construct a Path2D
object:
-
Path2D()
-
The
Path2D()
constructor returns a newly instantiatedPath2D
object, optionally with another path equally an statement (creates a re-create), or optionally with a string consisting of SVG path data.
new Path2D ( ) ; // empty path object new Path2D (path) ; // copy from another Path2D object new Path2D (d) ; // path from SVG path data
All path methods like moveTo
, rect
, arc
or quadraticCurveTo
, etc., which we got to know above, are available on Path2D
objects.
The Path2D
API also adds a way to combine paths using the addPath
method. This can exist useful when you want to build objects from several components, for example.
-
Path2D.addPath(path [, transform])
-
Adds a path to the current path with an optional transformation matrix.
Path2D example
In this example, we are creating a rectangle and a circle. Both are stored as a Path2D
object, and so that they are available for later on usage. With the new Path2D
API, several methods got updated to optionally accept a Path2D
object to use instead of the electric current path. Here, stroke
and fill
are used with a path argument to draw both objects onto the canvas, for case.
function depict ( ) { var sheet = document. getElementById ( 'sheet' ) ; if (canvas.getContext) { var ctx = canvas. getContext ( '2nd' ) ; var rectangle = new Path2D ( ) ; rectangle. rect ( 10 , 10 , 50 , 50 ) ; var circle = new Path2D ( ) ; circle. arc ( 100 , 35 , 25 , 0 , 2 * Math. PI ) ; ctx. stroke (rectangle) ; ctx. fill (circumvolve) ; } }
Using SVG paths
Another powerful feature of the new canvas Path2D
API is using SVG path data to initialize paths on your canvas. This might allow you to pass effectually path data and re-utilise them in both, SVG and canvas.
The path will move to indicate (M10 10
) and then move horizontally 80 points to the right (h 80
), then fourscore points down (five 80
), and so 80 points to the left (h -fourscore
), and and so dorsum to the start (z
). You can see this case on the Path2D
constructor page.
var p = new Path2D ( 'M10 10 h 80 v eighty h -80 Z' ) ;
- « Previous
- Adjacent »
doylehasheivates38.blogspot.com
Source: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes
0 Response to "Draw a Circle Using Triangle"
Post a Comment