Draw a Circle Using Javascript
Drawing shapes with sail
- « Previous
- Next »
Now that we have set upwardly our canvas surroundings, nosotros can get into the details of how to draw on the canvass. Past the finish of this article, you will accept learned how to draw rectangles, triangles, lines, arcs and curves, providing familiarity with some of the basic shapes. Working with paths is essential when drawing objects onto the sail and nosotros will meet how that can be done.
The grid
Before we can showtime drawing, we demand to talk about the sheet grid or coordinate space. Our HTML skeleton from the previous page had a canvas chemical element 150 pixels wide and 150 pixels high.
Normally i unit in the grid corresponds to 1 pixel on the canvas. The origin of this grid is positioned in the top left corner at coordinate (0,0). All elements are placed relative to this origin. So the position of the pinnacle left corner of the blue foursquare becomes x pixels from the left and y pixels from the height, at coordinate (x,y). After in this tutorial we'll see how nosotros tin interpret the origin to a different position, rotate the grid and fifty-fifty scale information technology, but for now we'll stick to the default.
Cartoon rectangles
Dissimilar SVG, <canvas>
only supports ii primitive shapes: rectangles and paths (lists of points connected by lines). All other shapes must exist created by combining one or more paths. Luckily, we take an array of path drawing functions which make it possible to compose very complex shapes.
Kickoff let's look at the rectangle. There are 3 functions that describe rectangles on the canvas:
-
fillRect(x, y, width, height)
-
Draws a filled rectangle.
-
strokeRect(x, y, width, pinnacle)
-
Draws a rectangular outline.
-
clearRect(x, y, width, height)
-
Clears the specified rectangular expanse, making it fully transparent.
Each of these 3 functions takes the same parameters. x
and y
specify the position on the canvas (relative to the origin) of the meridian-left corner of the rectangle. width
and height
provide the rectangle's size.
Below is the draw()
part from the previous page, but now information technology is making use of these three functions.
Rectangular shape example
function depict ( ) { var canvass = certificate. getElementById ( 'canvas' ) ; if (sail.getContext) { var ctx = canvas. getContext ( '2d' ) ; ctx. fillRect ( 25 , 25 , 100 , 100 ) ; ctx. clearRect ( 45 , 45 , 60 , 60 ) ; ctx. strokeRect ( 50 , 50 , 50 , 50 ) ; } }
This example'due south output is shown below.
The fillRect()
function draws a large black square 100 pixels on each side. The clearRect()
role then erases a 60x60 pixel square from the center, and and then strokeRect()
is called to create a rectangular outline 50x50 pixels within the cleared square.
In upcoming pages we'll meet 2 alternative methods for clearRect()
, and we'll also see how to change the colour and stroke style of the rendered shapes.
Unlike the path functions we'll encounter in the adjacent department, all three rectangle functions draw immediately to the sail.
Drawing paths
Now let'south await at paths. A path is a listing of points, connected by segments of lines that can exist of different shapes, curved or not, of different width and of unlike color. A path, or even a subpath, can be closed. To make shapes using paths, we take some extra steps:
- Beginning, y'all create the path.
- And so you apply drawing commands to draw into the path.
- Once the path has been created, you can stroke or fill the path to render it.
Here are the functions used to perform these steps:
-
beginPath()
-
Creates a new path. In one case created, future drawing commands are directed into the path and used to build the path up.
- Path methods
-
Methods to set different paths for objects.
-
closePath()
-
Adds a straight line to the path, going to the offset of the electric current sub-path.
-
stroke()
-
Draws the shape by stroking its outline.
-
fill up()
-
Draws a solid shape by filling the path'south content area.
The first footstep to create a path is to phone call the beginPath()
. Internally, paths are stored as a list of sub-paths (lines, arcs, etc) which together form a shape. Every fourth dimension this method is called, the list is reset and we can start drawing new shapes.
Note: When the current path is empty, such every bit immediately afterwards calling beginPath()
, or on a newly created canvas, the first path construction command is e'er treated equally a moveTo()
, regardless of what it actually is. For that reason, you volition almost e'er want to specifically ready your starting position subsequently resetting a path.
The 2d step is calling the methods that actually specify the paths to be fatigued. We'll see these shortly.
The third, and an optional step, is to telephone call closePath()
. This method tries to shut the shape by drawing a direct line from the current betoken to the start. If the shape has already been closed or at that place's only one betoken in the list, this office does zippo.
Note: When yous call fill up()
, whatever open shapes are closed automatically, and so yous don't have to call closePath()
. This is not the case when you call stroke()
.
Drawing a triangle
For example, the code for drawing a triangle would look something similar this:
role describe ( ) { var canvas = document. getElementById ( 'canvas' ) ; if (canvas.getContext) { var ctx = sheet. getContext ( '2d' ) ; ctx. beginPath ( ) ; ctx. moveTo ( 75 , 50 ) ; ctx. lineTo ( 100 , 75 ) ; ctx. lineTo ( 100 , 25 ) ; ctx. fill up ( ) ; } }
The effect looks like this:
Moving the pen
1 very useful office, which doesn't actually describe annihilation but becomes role of the path listing described higher up, is the moveTo()
function. You tin can probably best think of this as lifting a pen or pencil from ane spot on a piece of paper and placing information technology on the next.
-
moveTo(x, y)
-
Moves the pen to the coordinates specified past
10
andy
.
When the canvas is initialized or beginPath()
is called, you typically will desire to utilize the moveTo()
function to place the starting point somewhere else. We could also use moveTo()
to draw unconnected paths. Accept a wait at the smiley face below.
To try this for yourself, y'all can use the lawmaking snippet beneath. Just paste it into the draw()
function we saw before.
part draw ( ) { var sheet = document. getElementById ( 'canvas' ) ; if (canvas.getContext) { var ctx = sail. getContext ( '2d' ) ; 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 , faux ) ; // Mouth (clockwise) ctx. moveTo ( 65 , 65 ) ; ctx. arc ( lx , 65 , 5 , 0 , Math. PI * 2 , truthful ) ; // Left middle ctx. moveTo ( 95 , 65 ) ; ctx. arc ( 90 , 65 , v , 0 , Math. PI * 2 , true ) ; // Correct center ctx. stroke ( ) ; } }
The result looks like this:
If you'd similar to see the connecting lines, you can remove the lines that call moveTo()
.
Note: To learn more than well-nigh the arc()
function, run into the Arcs department beneath.
Lines
For drawing straight lines, utilise the lineTo()
method.
-
lineTo(10, y)
-
Draws a line from the current drawing position to the position specified past
x
andy
.
This method takes two arguments, x
and y
, which are the coordinates of the line's end point. The starting bespeak is dependent on previously fatigued paths, where the terminate point of the previous path is the starting bespeak for the following, etc. The starting point can also be changed past using the moveTo()
method.
The case below draws two triangles, one filled and one outlined.
part draw ( ) { var canvas = document. getElementById ( 'canvass' ) ; if (canvas.getContext) { var ctx = canvas. getContext ( '2nd' ) ; // 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 start a new shape path. We and then use the moveTo()
method to move the starting point to the desired position. Below this, two lines are drawn which make up two sides of the triangle.
Yous'll observe the departure betwixt the filled and stroked triangle. This is, as mentioned above, because shapes are automatically closed when a path is filled, but non when they are stroked. If we left out the closePath()
for the stroked triangle, but two lines would take been drawn, not a complete triangle.
Arcs
To draw arcs or circles, we use the arc()
or arcTo()
methods.
-
arc(10, y, radius, startAngle, endAngle, counterclockwise)
-
Draws an arc which is centered at (x, y) position with radius r starting at startAngle and catastrophe at endAngle going in the given direction indicated by counterclockwise (defaulting to clockwise).
-
arcTo(x1, y1, x2, y2, radius)
-
Draws an arc with the given control points and radius, connected to the previous signal by a straight line.
Allow'south have a more than detailed look at the arc
method, which takes 6 parameters: 10
and y
are the coordinates of the middle of the circle on which the arc should exist drawn. radius
is self-explanatory. The startAngle
and endAngle
parameters define the start and end points of the arc in radians, along 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.
Notation: Angles in the arc
function are measured in radians, not degrees. To catechumen degrees to radians you can utilise the following JavaScript expression: radians = (Math.PI/180)*degrees
.
The following example is a little more circuitous than the ones we've seen to a higher place. It draws 12 dissimilar arcs all with unlike angles and fills.
The 2 for
loops are for looping through the rows and columns of arcs. For each arc, we 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 do that in real life.
The x
and y
coordinates should be clear enough. radius
and startAngle
are fixed. The endAngle
starts at 180 degrees (half a circle) in the commencement column and is increased by steps of 90 degrees, culminating in a complete circle in the last column.
The argument for the clockwise
parameter results in the commencement and third row being drawn equally clockwise arcs and the second and 4th row as counterclockwise arcs. Finally, the if
statement makes the top half stroked arcs and the lesser half filled arcs.
Note: This example requires a slightly larger sheet than the others on this page: 150 x 200 pixels.
function draw ( ) { var sheet = certificate. getElementById ( 'canvas' ) ; if (sail.getContext) { var ctx = canvas. getContext ( '2d' ) ; for ( var i = 0 ; i < four ; i++ ) { for ( var j = 0 ; j < iii ; j++ ) { ctx. beginPath ( ) ; var x = 25 + j * 50 ; // x coordinate var y = 25 + i * l ; // y coordinate var radius = 20 ; // Arc radius var startAngle = 0 ; // Starting betoken on circle var endAngle = Math. PI + (Math. PI * j) / 2 ; // End bespeak on circle var counterclockwise = i % 2 !== 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 next type of paths bachelor are Bézier curves, available in both cubic and quadratic varieties. These are generally used to describe complex organic shapes.
-
quadraticCurveTo(cp1x, cp1y, x, y)
-
Draws a quadratic Bézier curve from the current pen position to the cease point specified by
x
andy
, using the control point specified bycp1x
andcp1y
. -
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
-
Draws a cubic Bézier curve from the electric current pen position to the cease point specified by
x
andy
, using the command points specified past (cp1x
,cp1y
) and (cp2x, cp2y).
The difference between these is that a quadratic Bézier curve has a start and an finish point (blueish dots) and just one command signal (indicated past the blood-red dot) while a cubic Bézier curve uses two 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 first control point, and cp2x
and cp2y
are the coordinates of the second command point.
Using quadratic and cubic Bézier curves tin be quite challenging, because different vector drawing software like Adobe Illustrator, we don't take direct visual feedback as to what nosotros're doing. This makes it pretty hard to draw complex shapes. In the post-obit case, we'll be drawing some elementary organic shapes, but if you accept the time and, most of all, the patience, much more circuitous shapes tin be created.
There's null very difficult in these examples. In both cases we come across a succession of curves being fatigued which finally outcome in a complete shape.
Quadratic Bezier curves
This example uses multiple quadratic Bézier curves to render a speech balloon.
function draw ( ) { var sheet = certificate. getElementById ( 'canvas' ) ; if (sheet.getContext) { var ctx = sheet. getContext ( '2d' ) ; // Quadratic curves instance ctx. beginPath ( ) ; ctx. moveTo ( 75 , 25 ) ; ctx. quadraticCurveTo ( 25 , 25 , 25 , 62.5 ) ; ctx. quadraticCurveTo ( 25 , 100 , 50 , 100 ) ; ctx. quadraticCurveTo ( 50 , 120 , thirty , 125 ) ; ctx. quadraticCurveTo ( 60 , 120 , 65 , 100 ) ; ctx. quadraticCurveTo ( 125 , 100 , 125 , 62.five ) ; ctx. quadraticCurveTo ( 125 , 25 , 75 , 25 ) ; ctx. stroke ( ) ; } }
Cubic Bezier curves
This instance draws a heart using cubic Bézier curves.
part draw ( ) { var canvas = certificate. getElementById ( 'sail' ) ; if (canvas.getContext) { var ctx = canvas. getContext ( '2nd' ) ; // Cubic curves instance ctx. beginPath ( ) ; ctx. moveTo ( 75 , 40 ) ; ctx. bezierCurveTo ( 75 , 37 , 70 , 25 , l , 25 ) ; ctx. bezierCurveTo ( xx , 25 , xx , 62.5 , 20 , 62.5 ) ; ctx. bezierCurveTo ( twenty , 80 , 40 , 102 , 75 , 120 ) ; ctx. bezierCurveTo ( 110 , 102 , 130 , lxxx , 130 , 62.5 ) ; ctx. bezierCurveTo ( 130 , 62.v , 130 , 25 , 100 , 25 ) ; ctx. bezierCurveTo ( 85 , 25 , 75 , 37 , 75 , xl ) ; ctx. fill up ( ) ; } }
Rectangles
In addition to the iii methods we saw in Drawing rectangles, which draw rectangular shapes directly to the canvas, there's also the rect()
method, which adds a rectangular path to a currently open path.
-
rect(x, y, width, height)
-
Draws a rectangle whose acme-left corner is specified by (
10
,y
) with the specifiedwidth
andelevation
.
Before 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
So far, each example on this page has used only i type of path function per shape. All the same, there's no limitation to the number or types of paths you can employ to create a shape. And then in this final example, let's combine all of the path functions to make a set up of very famous game characters.
office draw ( ) { var canvas = document. getElementById ( 'canvas' ) ; if (canvas.getContext) { var ctx = sail. 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 , xvi , half-dozen ) ; roundedRect (ctx, 135 , 53 , 49 , 33 , 10 ) ; roundedRect (ctx, 135 , 119 , 25 , 49 , x ) ; ctx. beginPath ( ) ; ctx. arc ( 37 , 37 , 13 , Math. PI / 7 , -Math. PI / vii , false ) ; ctx. lineTo ( 31 , 37 ) ; ctx. fill ( ) ; for ( var i = 0 ; i < eight ; i++ ) { ctx. fillRect ( 51 + i * 16 , 35 , four , four ) ; } for (i = 0 ; i < half dozen ; i++ ) { ctx. fillRect ( 115 , 51 + i * 16 , iv , 4 ) ; } for (i = 0 ; i < eight ; 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 * ii , true ) ; ctx. make full ( ) ; ctx. beginPath ( ) ; ctx. arc ( 89 , 102 , 2 , 0 , Math. PI * 2 , truthful ) ; ctx. fill ( ) ; } } // A utility function to depict a rectangle with rounded corners. function roundedRect ( ctx, 10, y, width, height, radius ) { ctx. beginPath ( ) ; ctx. moveTo (x, y + radius) ; ctx. arcTo (x, y + superlative, x + radius, y + height, radius) ; ctx. arcTo (x + width, y + height, x + width, y + height - radius, radius) ; ctx. arcTo (ten + width, y, x + width - radius, y, radius) ; ctx. arcTo (ten, y, x, y + radius, radius) ; ctx. stroke ( ) ; }
The resulting epitome looks like this:
We won't go over this in detail, since it'south really surprisingly uncomplicated. The most important things to note are the utilize of the fillStyle
belongings on the drawing context, and the utilise of a utility function (in this case roundedRect()
). Using utility functions for $.25 of drawing you do often can be very helpful and reduce the corporeality of lawmaking y'all need, as well every bit its complexity.
Nosotros'll take another expect at fillStyle
, in more detail, subsequently in this tutorial. Here, all we're doing is using it to change the fill color for paths from the default colour of black to white, and then back again.
Path2D objects
As nosotros take seen in the final example, at that place tin be a serial of paths and cartoon commands to draw objects onto your sheet. To simplify the code and to better performance, the Path2D
object, available in recent versions of browsers, lets you enshroud or record these drawing commands. You are able to play back your paths chop-chop. Allow'due south see how we can construct a Path2D
object:
-
Path2D()
-
The
Path2D()
constructor returns a newly instantiatedPath2D
object, optionally with another path as an argument (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 bachelor on Path2D
objects.
The Path2D
API also adds a manner to combine paths using the addPath
method. This can be useful when y'all 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 case
In this example, we are creating a rectangle and a circle. Both are stored as a Path2D
object, and then that they are available for subsequently usage. With the new Path2D
API, several methods got updated to optionally accept a Path2D
object to use instead of the current path. Here, stroke
and fill
are used with a path statement to draw both objects onto the canvas, for example.
function describe ( ) { var canvas = certificate. getElementById ( 'canvass' ) ; if (canvas.getContext) { var ctx = canvas. getContext ( 'second' ) ; var rectangle = new Path2D ( ) ; rectangle. rect ( x , x , 50 , 50 ) ; var circle = new Path2D ( ) ; circle. arc ( 100 , 35 , 25 , 0 , 2 * Math. PI ) ; ctx. stroke (rectangle) ; ctx. fill (circle) ; } }
Using SVG paths
Another powerful feature of the new canvas Path2D
API is using SVG path information to initialize paths on your canvas. This might allow you to pass around path data and re-utilise them in both, SVG and sheet.
The path will move to point (M10 10
) and then move horizontally eighty points to the correct (h 80
), then 80 points down (v lxxx
), and then 80 points to the left (h -80
), and then dorsum to the offset (z
). You can see this example on the Path2D
constructor page.
var p = new Path2D ( 'M10 10 h 80 five fourscore h -80 Z' ) ;
- « Previous
- Next »
Source: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes
0 Response to "Draw a Circle Using Javascript"
Post a Comment