Skip to content Skip to sidebar Skip to footer

Draw a Circle in Js

Drawing graphics

Graphics on the Web

Every bit we talked about in our HTML Multimedia and embedding module, the Web was originally but text, which was very dull, so images were introduced — first via the <img> element and later on via CSS properties such as background-prototype, and SVG.

This however was all the same not enough. While you could utilise CSS and JavaScript to animate (and otherwise dispense) SVG vector images — as they are represented by markup — in that location was however no way to do the aforementioned for bitmap images, and the tools available were rather limited. The Spider web still had no way to effectively create animations, games, 3D scenes, and other requirements usually handled by lower level languages such as C++ or Coffee.

The state of affairs started to improve when browsers began to support the <canvas> element and associated Sail API — Apple invented it in around 2004, and other browsers followed past implementing it in the years that followed. As you'll see below, canvas provides many useful tools for creating 2nd animations, games, data visualizations, and other types of app, peculiarly when combined with some of the other APIs the web platform provides.

The below example shows a unproblematic 2D canvas-based bouncing balls animation that we originally met in our Introducing JavaScript objects module:

Effectually 2006–2007, Mozilla started piece of work on an experimental 3D canvas implementation. This became WebGL, which gained traction among browser vendors, and was standardized around 2009–2010. WebGL allows you to create real 3D graphics within your spider web browser; the beneath example shows a simple rotating WebGL cube:

This article will focus mainly on 2nd sheet, as raw WebGL code is very circuitous. We will however show how to employ a WebGL library to create a 3D scene more hands, and y'all tin can find a tutorial covering raw WebGL elsewhere — run into Getting started with WebGL.

Note: Basic canvas functionality is supported well across browsers, with the exception of IE 8 and beneath for 2d canvas, and IE 11 and below for WebGL.

Active learning: Getting started with a <sail>

If you want to create a 2D or 3D scene on a web page, yous need to start with an HTML <canvass> chemical element. This chemical element is used to ascertain the area on the page into which the image will be fatigued. This is as simple as including the element on the page:

                                                                            <canvass                    width                                          =                      "320"                                        tiptop                                          =                      "240"                                        >                                                                              </sheet                    >                                                

This will create a canvas on the page with a size of 320 by 240 pixels.

Inside the sheet tags, y'all can put some fallback content, which is shown if the user's browser doesn't back up canvass.

                                                                            <canvas                    width                                          =                      "320"                                        height                                          =                      "240"                                        >                                                                              <p                    >                  Your browser doesn't support canvas. Boo hoo!                                          </p                    >                                                                              </sail                    >                                                

Of course, the above message is really unhelpful! In a real example you'd want to relate the fallback content to the canvass content. For example, if yous were rendering a constantly updating graph of stock prices, the fallback content could be a static image of the latest stock graph, with alt text saying what the prices are in text.

Creating and sizing our canvass

Permit'south kickoff by creating our own canvas that we draw future experiments on to.

  1. First brand a local copy of the 0_canvas_start directory. It contains iii files:
    • "index.html"
    • "script.js"
    • "manner.css"
  2. Open "index.html", and add the following lawmaking into it, just below the opening <trunk> tag:
                                                                                                <canvas                        grade                                                  =                          "myCanvas"                                                >                                                                                              <p                        >                      Add suitable fallback here.                                                  </p                        >                                                                                              </sail                        >                                                            
    We take added a class to the <canvas> element and so it will be easier to select if we have multiple canvases on the page, but we have removed the width and height attributes for at present (you could add them back in if you lot wanted, simply we will set them using JavaScript in a below department). Canvases with no explicit width and superlative default to 300 pixels wide by 150 pixels high.
  3. Now open "script.js" and add together the post-obit lines of JavaScript:
                                              const                      sail                      =                      document.                      querySelector                      (                      '.myCanvas'                      )                      ;                      const                      width                      =                      canvas.width                      =                      window.innerWidth;                      const                      height                      =                      canvas.elevation                      =                      window.innerHeight;                                      
    Here we take stored a reference to the canvas in the canvas constant. In the second line we set both a new constant width and the canvas' width belongings equal to Window.innerWidth (which gives us the viewport width). In the third line we set both a new constant elevation and the canvas' acme property equal to Window.innerHeight (which gives us the viewport height). So at present we take a canvas that fills the entire width and top of the browser window! You'll also see that we are chaining assignments together with multiple equals signs — this is allowed in JavaScript, and information technology is a good technique if y'all desire to brand multiple variables all equal to the same value. We wanted to make the canvas width and pinnacle hands accessible in the width/height variables, every bit they are useful values to accept available for later (for example, if you desire to draw something exactly halfway across the width of the canvas).

Note: Yous should generally gear up the size of the prototype using HTML attributes or DOM properties, as explained in a higher place. You could apply CSS, merely the trouble then is that the sizing is washed later the sail has rendered, and just like whatsoever other image (the rendered canvass is but an image), the image could get pixelated/distorted.

Getting the sail context and final setup

We need to do ane final affair earlier we can consider our canvas template finished. To draw onto the canvas we need to go a special reference to the cartoon expanse called a context. This is washed using the HTMLCanvasElement.getContext() method, which for basic usage takes a single cord as a parameter representing the type of context you want to call back.

In this case we want a 2d canvas, so add the following JavaScript line beneath the others in "script.js":

                                  const                  ctx                  =                  canvas.                  getContext                  (                  '2d'                  )                  ;                              

Note: other context values y'all could choose include webgl for WebGL, webgl2 for WebGL 2, etc., but we won't need those in this article.

And then that's information technology — our canvas is at present primed and ready for drawing on! The ctx variable now contains a CanvasRenderingContext2D object, and all drawing operations on the sail will involve manipulating this object.

Permit'due south practice one last thing before we motion on. We'll color the canvas groundwork black to give you a first taste of the canvas API. Add together the post-obit lines at the lesser of your JavaScript:

                ctx.fillStyle                  =                  'rgb(0, 0, 0)'                  ;                  ctx.                  fillRect                  (                  0                  ,                  0                  ,                  width,                  superlative)                  ;                              

Here we are setting a fill up colour using the canvas' fillStyle property (this takes color values merely like CSS backdrop do), then drawing a rectangle that covers the entire surface area of the sheet with thefillRect method (the offset ii parameters are the coordinates of the rectangle'due south top left hand corner; the last 2 are the width and top you want the rectangle drawn at — nosotros told you those width and peak variables would be useful)!

OK, our template is done and it's time to move on.

2D canvas basics

Every bit we said above, all drawing operations are washed by manipulating a CanvasRenderingContext2D object (in our instance, ctx). Many operations need to be given coordinates to pinpoint exactly where to describe something — the top left of the canvas is point (0, 0), the horizontal (10) axis runs from left to right, and the vertical (y) axis runs from top to bottom.

Cartoon shapes tends to be done using the rectangle shape archaic, or by tracing a line along a certain path and so filling in the shape. Below we'll testify how to do both.

Simple rectangles

Allow'due south first with some simple rectangles.

  1. Get-go of all, take a copy of your newly coded canvass template (or make a local copy of the 1_canvas_template directory if you didn't follow the above steps).
  2. Next, add the following lines to the bottom of your JavaScript:
                        ctx.fillStyle                      =                      'rgb(255, 0, 0)'                      ;                      ctx.                      fillRect                      (                      50                      ,                      l                      ,                      100                      ,                      150                      )                      ;                                      
    If you salve and refresh, you should come across a red rectangle has appeared on your sheet. Its summit left corner is l pixels away from the top and left of the canvas edge (as defined by the first two parameters), and it is 100 pixels broad and 150 pixels tall (as defined by the tertiary and 4th parameters).
  3. Allow's add another rectangle into the mix — a green one this time. Add together the post-obit at the bottom of your JavaScript:
                        ctx.fillStyle                      =                      'rgb(0, 255, 0)'                      ;                      ctx.                      fillRect                      (                      75                      ,                      75                      ,                      100                      ,                      100                      )                      ;                                      
    Save and refresh, and you lot'll meet your new rectangle. This raises an of import signal: graphics operations like drawing rectangles, lines, and so along are performed in the club in which they occur. Think of it like painting a wall, where each glaze of pigment overlaps and may fifty-fifty hide what's underneath. You can't exercise anything to alter this, so you have to call up carefully about the gild in which y'all depict the graphics.
  4. Note that y'all can describe semi-transparent graphics past specifying a semi-transparent color, for example by using rgba(). The a value defines what's chosen the "alpha channel, " or the amount of transparency the color has. The college its value, the more it will obscure whatsoever'southward behind information technology. Add the following to your lawmaking:
                        ctx.fillStyle                      =                      'rgba(255, 0, 255, 0.75)'                      ;                      ctx.                      fillRect                      (                      25                      ,                      100                      ,                      175                      ,                      50                      )                      ;                                      
  5. Now endeavor drawing some more than rectangles of your own; take fun!

Strokes and line widths

Then far we've looked at drawing filled rectangles, only you can likewise draw rectangles that are just outlines (chosen strokes in graphic design). To set the color you desire for your stroke, you use the strokeStyle belongings; drawing a stroke rectangle is done using strokeRect.

  1. Add together the following to the previous example, again below the previous JavaScript lines:
                        ctx.strokeStyle                      =                      'rgb(255, 255, 255)'                      ;                      ctx.                      strokeRect                      (                      25                      ,                      25                      ,                      175                      ,                      200                      )                      ;                                      
  2. The default width of strokes is 1 pixel; you tin can suit the lineWidth property value to alter this (information technology takes a number representing the number of pixels wide the stroke is). Add the following line in between the previous two lines:

At present you should run into that your white outline has go much thicker! That's information technology for now. At this betoken your example should look like this:

Cartoon paths

If you desire to draw anything more complex than a rectangle, you demand to describe a path. Basically, this involves writing code to specify exactly what path the pen should move along on your sail to trace the shape y'all desire to describe. Canvas includes functions for drawing straight lines, circles, Bézier curves, and more than.

Let's get-go the section off by making a fresh copy of our canvas template (1_canvas_template), in which to draw the new case.

We'll exist using some common methods and properties across all of the below sections:

  • beginPath() — start drawing a path at the signal where the pen currently is on the canvas. On a new canvas, the pen starts out at (0, 0).
  • moveTo() — move the pen to a different indicate on the sail, without recording or tracing the line; the pen "jumps" to the new position.
  • fill() — draw a filled shape past filling in the path you've traced then far.
  • stroke() — depict an outline shape past cartoon a stroke forth the path you've fatigued so far.
  • You tin besides use features similar lineWidth and fillStyle/strokeStyle with paths as well equally rectangles.

A typical, simple path-drawing performance would expect something like so:

                ctx.fillStyle                  =                  'rgb(255, 0, 0)'                  ;                  ctx.                  beginPath                  (                  )                  ;                  ctx.                  moveTo                  (                  50                  ,                  fifty                  )                  ;                  // draw your path                  ctx.                  make full                  (                  )                  ;                              

Drawing lines

Let's draw an equilateral triangle on the canvass.

  1. First of all, add the post-obit helper function to the bottom of your lawmaking. This converts degree values to radians, which is useful because whenever you need to provide an angle value in JavaScript, it volition almost always be in radians, but humans usually recall in degrees.
                                              function                      degToRad                      (                      degrees                      )                      {                      return                      degrees                      *                      Math.                      PI                      /                      180                      ;                      }                                      
  2. Next, start off your path by adding the following below your previous improver; here we set up a color for our triangle, start cartoon a path, and and then move the pen to (50, fifty) without drawing anything. That'southward where we'll start drawing our triangle.
                        ctx.fillStyle                      =                      'rgb(255, 0, 0)'                      ;                      ctx.                      beginPath                      (                      )                      ;                      ctx.                      moveTo                      (                      50                      ,                      50                      )                      ;                                      
  3. Now add the following lines at the bottom of your script:
                        ctx.                      lineTo                      (                      150                      ,                      50                      )                      ;                      const                      triHeight                      =                      50                      *                      Math.                      tan                      (                      degToRad                      (                      threescore                      )                      )                      ;                      ctx.                      lineTo                      (                      100                      ,                      l                      +                      triHeight)                      ;                      ctx.                      lineTo                      (                      50                      ,                      50                      )                      ;                      ctx.                      fill                      (                      )                      ;                                      
    Let's run through this in club: First we depict a line across to (150, fifty) — our path at present goes 100 pixels to the right along the x axis. 2d, we piece of work out the pinnacle of our equilateral triangle, using a bit of elementary trigonometry. Basically, we are drawing the triangle pointing downward. The angles in an equilateral triangle are e'er 60 degrees; to work out the elevation nosotros can divide it down the middle into ii correct-angled triangles, which will each have angles of xc degrees, 60 degrees, and 30 degrees. In terms of the sides:
    • The longest side is chosen the hypotenuse
    • The side side by side to the 60 degree angle is called the adjacent — which nosotros know is 50 pixels, as it is half of the line we just drew.
    • The side opposite the sixty degree bending is called the opposite, which is the height of the triangle we want to calculate.
    One of the basic trigonometric formulae states that the length of the next multiplied past the tangent of the angle is equal to the opposite, hence we come upwardly with 50 * Math.tan(degToRad(lx)). We apply our degToRad() function to catechumen 60 degrees to radians, as Math.tan() expects an input value in radians.
  4. With the meridian calculated, we draw another line to (100, 50 + triHeight). The X coordinate is simple; information technology must be halfway betwixt the previous two Ten values we fix. The Y value on the other hand must be 50 plus the triangle height, as we know the summit of the triangle is 50 pixels from the tiptop of the sheet.
  5. The side by side line draws a line dorsum to the starting indicate of the triangle.
  6. Terminal of all, nosotros run ctx.fill() to terminate the path and fill up in the shape.

Drawing circles

At present let'due south look at how to draw a circle in sail. This is accomplished using the arc() method, which draws all or role of a circle at a specified point.

  1. Let's add an arc to our canvas — add the post-obit to the bottom of your code:
                        ctx.fillStyle                      =                      'rgb(0, 0, 255)'                      ;                      ctx.                      beginPath                      (                      )                      ;                      ctx.                      arc                      (                      150                      ,                      106                      ,                      50                      ,                      degToRad                      (                      0                      )                      ,                      degToRad                      (                      360                      )                      ,                      imitation                      )                      ;                      ctx.                      fill                      (                      )                      ;                                      
    arc() takes six parameters. The first two specify the position of the arc'due south centre (X and Y, respectively). The third is the circumvolve's radius, the quaternary and fifth are the start and end angles at which to draw the circle (so specifying 0 and 360 degrees gives the states a full circle), and the sixth parameter defines whether the circle should be drawn counterclockwise (anticlockwise) or clockwise (false is clockwise).

    Note: 0 degrees is horizontally to the correct.

  2. Let's try adding some other arc:
                        ctx.fillStyle                      =                      'yellow'                      ;                      ctx.                      beginPath                      (                      )                      ;                      ctx.                      arc                      (                      200                      ,                      106                      ,                      50                      ,                      degToRad                      (                      -                      45                      )                      ,                      degToRad                      (                      45                      )                      ,                      true                      )                      ;                      ctx.                      lineTo                      (                      200                      ,                      106                      )                      ;                      ctx.                      fill up                      (                      )                      ;                                      
    The pattern here is very similar, just with two differences:
    • We have ready the terminal parameter of arc() to true, meaning that the arc is drawn counterclockwise, which means that even though the arc is specified equally starting at -45 degrees and ending at 45 degrees, nosotros draw the arc effectually the 270 degrees non inside this portion. If you were to change true to imitation and then re-run the code, but the 90 degree slice of the circle would be drawn.
    • Before calling fill(), nosotros describe a line to the center of the circle. This means that we go the rather nice Pac-Man-style cutout rendered. If you removed this line (try information technology!) then re-ran the code, you'd get merely an edge of the circumvolve chopped off betwixt the start and finish indicate of the arc. This illustrates another of import point of the canvas — if you effort to fill up an incomplete path (i.e. one that is not closed), the browser fills in a straight line betwixt the start and terminate point and then fills information technology in.

That's it for at present; your final example should look like this:

Note: The finished lawmaking is available on GitHub as 3_canvas_paths.

Note: To find out more about advanced path drawing features such as Bézier curves, bank check out our Drawing shapes with sail tutorial.

Text

Canvas as well has features for drawing text. Let's explore these briefly. Kickoff past making another fresh copy of our canvas template (1_canvas_template) in which to draw the new instance.

Text is fatigued using two methods:

  • fillText() — draws filled text.
  • strokeText() — draws outline (stroke) text.

Both of these take three backdrop in their basic usage: the text cord to draw and the X and Y coordinates of the bespeak to kickoff cartoon the text at. This works out as the bottom left corner of the text box (literally, the box surrounding the text you draw), which might confuse yous as other drawing operations tend to start from the top left corner — bear this in listen.

At that place are also a number of backdrop to assistance control text rendering such as font, which lets you specify font family, size, etc. It takes as its value the same syntax as the CSS font property.

Try calculation the following block to the bottom of your JavaScript:

                ctx.strokeStyle                  =                  'white'                  ;                  ctx.lineWidth                  =                  i                  ;                  ctx.font                  =                  '36px arial'                  ;                  ctx.                  strokeText                  (                  'Sail text'                  ,                  50                  ,                  50                  )                  ;                  ctx.fillStyle                  =                  'red'                  ;                  ctx.font                  =                  '48px georgia'                  ;                  ctx.                  fillText                  (                  'Sail text'                  ,                  50                  ,                  150                  )                  ;                              

Here we draw ii lines of text, one outline and the other stroke. The last example should look like so:

Note: The finished code is available on GitHub as 4_canvas_text.

Have a play and see what you tin come up up with! You tin can find more data on the options available for canvas text at Drawing text.

Drawing images onto canvas

It is possible to render external images onto your canvass. These can exist elementary images, frames from videos, or the content of other canvases. For the moment we'll just await at the example of using some simple images on our sheet.

  1. Every bit before, make another fresh re-create of our canvas template (1_canvas_template) in which to depict the new example. Images are drawn onto sail using the drawImage() method. The simplest version takes three parameters — a reference to the paradigm you want to render, and the 10 and Y coordinates of the image's acme left corner.
  2. Allow'due south commencement past getting an epitome source to embed in our canvas. Add the following lines to the bottom of your JavaScript:
                                              const                      image                      =                      new                      Image                      (                      )                      ;                      image.src                      =                      'firefox.png'                      ;                                      
    Here nosotros create a new HTMLImageElement object using the Image() constructor. The returned object is the same blazon as that which is returned when you grab a reference to an existing <img> element). Nosotros then set its src attribute to equal our Firefox logo image. At this indicate, the browser starts loading the image.
  3. Nosotros could now try to embed the image using drawImage(), but we demand to make sure the paradigm file has been loaded starting time, otherwise the code will fail. We tin achieve this using the load consequence, which will only be fired when the image has finished loading. Add the following cake below the previous i:
                        image.                      addEventListener                      (                      'load'                      ,                      (                      )                      =>                      ctx.                      drawImage                      (epitome,                      xx                      ,                      20                      ,                      185                      ,                      175                      ,                      50                      ,                      50                      ,                      185                      ,                      175                      )                      )                      ;                                      
    If you load your example in the browser now, you should run across the epitome embedded in the sheet.
  4. Only there's more! What if we want to display simply a part of the image, or to resize it? We tin can do both with the more complex version of drawImage(). Update your ctx.drawImage() line like and so:
                        ctx.                      drawImage                      (image,                      20                      ,                      20                      ,                      185                      ,                      175                      ,                      l                      ,                      50                      ,                      185                      ,                      175                      )                      ;                                      
    • The showtime parameter is the epitome reference, every bit before.
    • Parameters 2 and 3 define the coordinates of the meridian left corner of the area you want to cut out of the loaded image, relative to the top-left corner of the image itself. Zippo to the left of the beginning parameter or above the second will be drawn.
    • Parameters 4 and 5 define the width and height of the area we want to cutting out from the original image nosotros loaded.
    • Parameters six and seven define the coordinates at which you want to draw the top-left corner of the cut-out portion of the epitome, relative to the top-left corner of the sheet.
    • Parameters eight and 9 define the width and top to draw the cutting-out area of the image. In this instance, we have specified the same dimensions as the original slice, but you could resize it by specifying different values.

The concluding example should wait like and then:

Note: The finished lawmaking is bachelor on GitHub as 5_canvas_images.

Loops and animations

We have and then far covered some very basic uses of 2nd canvas, simply really you won't experience the full power of canvas unless you update or animate it in some mode. Subsequently all, sail does provide scriptable images! If you aren't going to modify annihilation, then you might besides but employ static images and save yourself all the piece of work.

Creating a loop

Playing with loops in canvas is rather fun — you can run sail commands inside a for (or other type of) loop just like whatever other JavaScript code.

Allow's build a simple example.

  1. Make some other fresh re-create of our canvass template (1_canvas_template) and open it in your code editor.
  2. Add the following line to the bottom of your JavaScript. This contains a new method, interpret(), which moves the origin point of the canvas:
                        ctx.                      translate                      (width/                      2                      ,                      tiptop/                      2                      )                      ;                                      
    This causes the coordinate origin (0, 0) to exist moved to the center of the canvas, rather than being at the top left corner. This is very useful in many situations, similar this one, where we desire our design to be drawn relative to the center of the sail.
  3. Now add the following lawmaking to the lesser of the JavaScript:
                                              function                      degToRad                      (                      degrees                      )                      {                      return                      degrees                      *                      Math.                      PI                      /                      180                      ;                      }                      function                      rand                      (                      min,                        max                      )                      {                      render                      Math.                      flooring                      (Math.                      random                      (                      )                      *                      (max-min+                      one                      )                      )                      +                      (min)                      ;                      }                      let                      length                      =                      250                      ;                      let                      moveOffset                      =                      20                      ;                      for                      (                      let                      i                      =                      0                      ;                      i                      <                      length;                      i++                      )                      {                      }                                      
    Here we are implementing the same degToRad() function nosotros saw in the triangle example higher up, a rand() part that returns a random number betwixt given lower and upper premises, length and moveOffset variables (which nosotros'll find out more about later), and an empty for loop.
  4. The idea hither is that we'll draw something on the canvas inside the for loop, and iterate on it each time so we can create something interesting. Add the following code within your for loop:
                        ctx.fillStyle                      =                                              `                        rgba(                                                  ${                          255                          -length}                                                ,0,                                                  ${                          255                          -length}                                                ,0.9)                        `                                            ;                      ctx.                      beginPath                      (                      )                      ;                      ctx.                      moveTo                      (moveOffset,moveOffset)                      ;                      ctx.                      lineTo                      (moveOffset+length,moveOffset)                      ;                      const                      triHeight                      =                      length/                      2                      *                      Math.                      tan                      (                      degToRad                      (                      60                      )                      )                      ;                      ctx.                      lineTo                      (moveOffset+                      (length/                      2                      )                      ,moveOffset+triHeight)                      ;                      ctx.                      lineTo                      (moveOffset,moveOffset)                      ;                      ctx.                      fill                      (                      )                      ;                      length--                      ;                      moveOffset                      +=                      0.seven                      ;                      ctx.                      rotate                      (                      degToRad                      (                      5                      )                      )                      ;                                      
    So on each iteration, we:
    • Ready the fillStyle to exist a shade of slightly transparent majestic, which changes each fourth dimension based on the value of length. Equally yous'll run across later the length gets smaller each time the loop runs, and so the result here is that the color gets brighter with each successive triangle drawn.
    • Begin the path.
    • Motion the pen to a coordinate of (moveOffset, moveOffset); This variable defines how far we want to motion each time nosotros draw a new triangle.
    • Draw a line to a coordinate of (moveOffset+length, moveOffset). This draws a line of length length parallel to the X axis.
    • Calculate the triangle'due south height, every bit earlier.
    • Draw a line to the down-pointing corner of the triangle, so draw a line dorsum to the start of the triangle.
    • Call fill() to make full in the triangle.
    • Update the variables that describe the sequence of triangles, so we tin can exist ready to describe the side by side one. Nosotros decrease the length value past i, so the triangles go smaller each time; increase moveOffset by a small amount and then each successive triangle is slightly farther abroad, and use some other new role, rotate(), which allows us to rotate the entire canvas! We rotate it by 5 degrees before drawing the adjacent triangle.

That's it! The final example should await like then:

At this indicate, nosotros'd like to encourage you to play with the example and brand it your own! For case:

  • Describe rectangles or arcs instead of triangles, or even embed images.
  • Play with the length and moveOffset values.
  • Introduce some random numbers using that rand() role we included above but didn't use.

Animations

The loop case we congenital above was fun, merely really you lot need a constant loop that keeps going and going for any serious canvas applications (such every bit games and existent fourth dimension visualizations). If yous call up of your sail every bit being similar a moving picture, y'all really want the display to update on each frame to show the updated view, with an ideal refresh rate of 60 frames per second so that movement appears squeamish and smooth to the man centre.

There are a few JavaScript functions that will allow y'all to run functions repeatedly, several times a 2d, the best one for our purposes hither being window.requestAnimationFrame(). It takes ane parameter — the name of the part you desire to run for each frame. The next time the browser is ready to update the screen, your function will get called. If that function draws the new update to your animation, then calls requestAnimationFrame() again just earlier the end of the office, the animation loop volition continue to run. The loop ends when y'all stop calling requestAnimationFrame() or if you call window.cancelAnimationFrame() later on calling requestAnimationFrame() but before the frame is called.

Notation: Information technology's skillful practice to phone call cancelAnimationFrame() from your master lawmaking when you're done using the blitheness, to ensure that no updates are nonetheless waiting to be run.

The browser works out complex details such as making the blitheness run at a consistent speed, and not wasting resource animating things that tin't be seen.

To run into how it works, permit's speedily expect over again at our Billowy Balls example (run into information technology live, and too see the source code). The code for the loop that keeps everything moving looks like this:

                                  function                  loop                  (                  )                  {                  ctx.fillStyle                  =                  'rgba(0, 0, 0, 0.25)'                  ;                  ctx.                  fillRect                  (                  0                  ,                  0                  ,                  width,                  peak)                  ;                  for                  (                  const                  ball                  of                  balls)                  {                  brawl.                  describe                  (                  )                  ;                  ball.                  update                  (                  )                  ;                  ball.                  collisionDetect                  (                  )                  ;                  }                  requestAnimationFrame                  (loop)                  ;                  }                  loop                  (                  )                  ;                              

Nosotros run the loop() role once at the lesser of the code to start the cycle, drawing the first blitheness frame; the loop() part so takes accuse of calling requestAnimationFrame(loop) to run the next frame of the blitheness, once more and again.

Note that on each frame we are completely clearing the canvas and redrawing everything. For every ball present we depict it, update its position, and check to come across if it is colliding with whatever other assurance. Once you've drawn a graphic to a canvas, there's no style to manipulate that graphic individually similar you lot can with DOM elements. You tin't movement each ball around on the canvas, because one time it's drawn, information technology's part of the canvas, and is not an private accessible element or object. Instead, you have to erase and redraw, either by erasing the entire frame and redrawing everything, or past having code that knows exactly what parts need to be erased and only erases and redraws the minimum area of the canvas necessary.

Optimizing animation of graphics is an entire specialty of programming, with lots of clever techniques bachelor. Those are beyond what we need for our example, though!

In full general, the procedure of doing a canvas animation involves the following steps:

  1. Clear the canvas contents (e.m. with fillRect() or clearRect()).
  2. Save country (if necessary) using save() — this is needed when yous want to salvage settings yous've updated on the canvass before continuing, which is useful for more than advanced applications.
  3. Draw the graphics y'all are animating.
  4. Restore the settings yous saved in footstep 2, using restore()
  5. Phone call requestAnimationFrame() to schedule drawing of the next frame of the animation.

Note: Nosotros won't cover salve() and restore() here, only they are explained nicely in our Transformations tutorial (and the ones that follow information technology).

A simple grapheme blitheness

At present allow's create our ain simple blitheness — nosotros'll go a grapheme from a sure rather awesome retro computer game to walk across the screen.

  1. Make another fresh copy of our sheet template (1_canvas_template) and open up it in your code editor.
  2. At the bottom of the JavaScript, add the following line to one time again make the coordinate origin sit down in the middle of the sail:
                        ctx.                      translate                      (width/                      2                      ,                      height/                      2                      )                      ;                                      
  3. Now let'southward create a new HTMLImageElement object, prepare its src to the image we desire to load, and add an onload effect handler that volition cause the draw() office to fire when the image is loaded:
                                              const                      image                      =                      new                      Image                      (                      )                      ;                      epitome.src                      =                      'walk-right.png'                      ;                      image.onload                      =                      draw;                                      
  4. Now nosotros'll add together some variables to go along track of the position the sprite is to exist drawn on the screen, and the sprite number nosotros want to display.
                                              allow                      sprite                      =                      0                      ;                      allow                      posX                      =                      0                      ;                                      
    Let'south explain the spritesheet prototype (which nosotros have respectfully borrowed from Mike Thomas' Create a sprite sheet walk cycle using CSS blitheness). The image looks like this: It contains half-dozen sprites that make upwardly the whole walking sequence — each one is 102 pixels wide and 148 pixels high. To display each sprite cleanly we will have to use drawImage() to chop out a single sprite prototype from the spritesheet and display simply that part, similar we did above with the Firefox logo. The X coordinate of the slice will accept to be a multiple of 102, and the Y coordinate volition ever be 0. The slice size will always be 102 by 148 pixels.
  5. Now allow's insert an empty depict() function at the bottom of the code, ready for filling up with some code:
  6. The residue of the code in this department goes inside draw(). First, add the post-obit line, which clears the canvas to prepare for drawing each frame. Notice that nosotros accept to specify the height-left corner of the rectangle as -(width/2), -(superlative/ii) because we specified the origin position as width/2, height/ii before on.
                        ctx.                      fillRect                      (                      -                      (width/                      two                      )                      ,                      -                      (elevation/                      2                      )                      ,                      width,                      height)                      ;                                      
  7. Next, we'll draw our image using drawImage — the 9-parameter version. Add the following:
                        ctx.                      drawImage                      (epitome,                      (sprite*                      102                      )                      ,                      0                      ,                      102                      ,                      148                      ,                      0                      +posX,                      -                      74                      ,                      102                      ,                      148                      )                      ;                                      
    As y'all can see:
    • Nosotros specify image every bit the image to embed.
    • Parameters two and three specify the superlative-left corner of the slice to cut out of the source paradigm, with the X value as sprite multiplied by 102 (where sprite is the sprite number between 0 and 5) and the Y value always 0.
    • Parameters 4 and 5 specify the size of the piece to cut out — 102 pixels by 148 pixels.
    • Parameters 6 and 7 specify the top-left corner of the box into which to draw the slice on the canvass — the X position is 0 + posX, pregnant that nosotros can modify the drawing position by altering the posX value.
    • Parameters 8 and 9 specify the size of the paradigm on the canvas. We just want to keep its original size, so we specify 102 and 148 every bit the width and tiptop.
  8. Now nosotros'll alter the sprite value after each draw — well, later on some of them anyway. Add the following block to the bottom of the describe() function:
                                              if                      (posX                      %                      13                      ===                      0                      )                      {                      if                      (sprite                      ===                      five                      )                      {                      sprite                      =                      0                      ;                      }                      else                      {                      sprite++                      ;                      }                      }                                      
    We are wrapping the whole cake in if (posX % 13 === 0) { ... }. We apply the modulo (%) operator (also known as the residuum operator) to check whether the posX value can exist exactly divided by 13 with no rest. If so, nosotros movement on to the next sprite by incrementing sprite (wrapping to 0 after we're done with sprite #5). This effectively means that we are only updating the sprite on every 13th frame, or roughly about 5 frames a 2d (requestAnimationFrame() calls us at upwards to sixty frames per second if possible). We are deliberately slowing down the frame rate considering we only have six sprites to work with, and if we display one every 60th of a 2d, our character volition motion manner too fast! Inside the outer cake we use an if ... else argument to cheque whether the sprite value is at 5 (the last sprite, given that the sprite numbers run from 0 to 5). If we are showing the concluding sprite already, we reset sprite dorsum to 0; if not we just increment it by 1.
  9. Side by side nosotros demand to work out how to change the posX value on each frame — add together the following code cake just beneath your last 1.
                                              if                      (posX                      >                      width/                      ii                      )                      {                      permit                      newStartPos                      =                      -                      (                      (width/                      2                      )                      +                      102                      )                      ;                      posX                      =                      Math.                      ceil                      (newStartPos)                      ;                      panel.                      log                      (posX)                      ;                      }                      else                      {                      posX                      +=                      2                      ;                      }                                      
    We are using another if ... else statement to see if the value of posX has become greater than width/2, which means our character has walked off the right border of the screen. If and so, we summate a position that would put the character just to the left of the left side of the screen. If our character hasn't yet walked off the edge of the screen, we increment posX by 2. This will make him move a little flake to the right the next time we draw him.
  10. Finally, we need to make the blitheness loop past calling requestAnimationFrame() at the bottom of the draw() function:
                        window.                      requestAnimationFrame                      (draw)                      ;                                      

That's information technology! The final example should look like so:

A simple drawing application

Equally a concluding blitheness case, we'd like to show you a very simple drawing application, to illustrate how the animation loop can exist combined with user input (like mouse movement, in this case). We won't get yous to walk through and build this 1; nosotros'll just explore the most interesting parts of the code.

The example tin can be found on GitHub as 8_canvas_drawing_app, and you can play with it live below:

Let's look at the nearly interesting parts. Get-go of all, we keep track of the mouse's 10 and Y coordinates and whether it is beingness clicked or not with three variables: curX, curY, and pressed. When the mouse moves, we fire a function set as the onmousemove event handler, which captures the current X and Y values. We as well utilize onmousedown and onmouseup event handlers to change the value of pressed to true when the mouse push button is pressed, and dorsum to imitation again when information technology is released.

                                  let                  curX;                  let                  curY;                  let                  pressed                  =                  imitation                  ;                  // update mouse pointer coordinates                  certificate.                  addEventListener                  (                  'mousemove'                  ,                  eastward                  =>                  {                  curX                  =                  (window.Consequence)                  ?                  e.pageX                  :                  e.clientX                  +                  (document.documentElement.scrollLeft                  ?                  certificate.documentElement.scrollLeft                  :                  document.body.scrollLeft)                  ;                  curY                  =                  (window.Event)                  ?                  e.pageY                  :                  due east.clientY                  +                  (document.documentElement.scrollTop                  ?                  document.documentElement.scrollTop                  :                  document.body.scrollTop)                  ;                  }                  )                  ;                  sheet.                  addEventListener                  (                  'mousedown'                  ,                  (                  )                  =>                  pressed                  =                  truthful                  )                  ;                  canvas.                  addEventListener                  (                  'mouseup'                  ,                  (                  )                  =>                  pressed                  =                  imitation                  )                  ;                              

When the "Articulate canvas" button is pressed, we run a uncomplicated function that clears the whole canvas back to black, the same style nosotros've seen before:

                clearBtn.                  addEventListener                  (                  'click'                  ,                  (                  )                  =>                  {                  ctx.fillStyle                  =                  'rgb(0,0,0)'                  ;                  ctx.                  fillRect                  (                  0                  ,                  0                  ,width,pinnacle)                  ;                  }                  )                  ;                              

The drawing loop is pretty unproblematic this time effectually — if pressed is truthful, we draw a circle with a fill style equal to the value in the color picker, and a radius equal to the value fix in the range input. We take to draw the circle 85 pixels higher up where we measured it from, considering the vertical measurement is taken from the pinnacle of the viewport, only we are drawing the circumvolve relative to the height of the sail, which starts beneath the 85 pixel-high toolbar. If we drew it with simply curY as the y coordinate, it would appear 85 pixels lower than the mouse position.

                                  function                  draw                  (                  )                  {                  if                  (pressed)                  {                  ctx.fillStyle                  =                  colorPicker.value;                  ctx.                  beginPath                  (                  )                  ;                  ctx.                  arc                  (curX,                  curY-                  85                  ,                  sizePicker.value,                  degToRad                  (                  0                  )                  ,                  degToRad                  (                  360                  )                  ,                  fake                  )                  ;                  ctx.                  fill                  (                  )                  ;                  }                  requestAnimationFrame                  (depict)                  ;                  }                  draw                  (                  )                  ;                              

Note: The <input> range and colour types are supported adequately well beyond browsers, with the exception of Internet Explorer versions less than 10; besides Safari doesn't however support color. If your browser doesn't support these inputs, they volition fall back to uncomplicated text fields and you'll but have to enter valid color/number values yourself.

WebGL

It's now time to go out second backside, and take a quick look at 3D canvas. 3D canvas content is specified using the WebGL API, which is a completely separate API from the 2nd canvass API, even though they both render onto <sheet> elements.

WebGL is based on OpenGL (Open Graphics Library), and allows you to communicate directly with the computer'southward GPU. Every bit such, writing raw WebGL is closer to low level languages such as C++ than regular JavaScript; information technology is quite complex but incredibly powerful.

Using a library

Because of its complication, nigh people write 3D graphics code using a third party JavaScript library such as Iii.js, PlayCanvas, or Babylon.js. Most of these work in a similar manner, providing functionality to create primitive and custom shapes, position viewing cameras and lighting, covering surfaces with textures, and more than. They handle the WebGL for you, letting you work on a higher level.

Yep, using 1 of these means learning another new API (a third party one, in this case), simply they are a lot simpler than coding raw WebGL.

Recreating our cube

Let's look at a simple example of how to create something with a WebGL library. We'll choose Three.js, as it is one of the nearly popular ones. In this tutorial we'll create the 3D spinning cube we saw earlier.

  1. To start with, make a local copy of threejs-cube/index.html in a new folder, then relieve a copy of metal003.png in the same folder. This is the image we'll use as a surface texture for the cube later on.
  2. Next, create a new file called script.js, again in the same binder every bit earlier.
  3. Adjacent, you need to download the three.min.js library and salvage it in the same directory as earlier.
  4. Now we've got three.js attached to our folio, nosotros tin start to write JavaScript that makes apply of it into script.js. Let'southward start past creating a new scene — add the following into your main.js file:
                                              const                      scene                      =                      new                      Iii.Scene                      (                      )                      ;                                      
    The Scene() constructor creates a new scene, which represents the whole 3D world we are trying to brandish.
  5. Side by side, we need a photographic camera so we tin can see the scene. In 3D imagery terms, the camera represents a viewer'southward position in the globe. To create a camera, add the following lines next:
                                              const                      camera                      =                      new                      THREE.PerspectiveCamera                      (                      75                      ,                      window.innerWidth                      /                      window.innerHeight,                      0.i                      ,                      yard                      )                      ;                      camera.position.z                      =                      v                      ;                                      
    The PerspectiveCamera() constructor takes iv arguments:
    • The field of view: How wide the expanse in front of the camera is that should exist visible onscreen, in degrees.
    • The aspect ratio: Usually, this is the ratio of the scene's width divided by the scene's height. Using another value will distort the scene (which might be what you desire, but normally isn't).
    • The virtually aeroplane: How close to the camera objects tin be before we stop rendering them to the screen. Call back nigh how when you move your fingertip closer and closer to the space betwixt your eyes, eventually you can't see it anymore.
    • The far plane: How far abroad things are from the photographic camera before they are no longer rendered.
    We also set the photographic camera's position to be 5 distance units out of the Z centrality, which, like in CSS, is out of the screen towards you, the viewer.
  6. The third vital ingredient is a renderer. This is an object that renders a given scene, equally viewed through a given camera. Nosotros'll create ane for now using the WebGLRenderer() constructor, but nosotros'll not employ it till afterwards. Add the following lines next:
                                              const                      renderer                      =                      new                      Iii.WebGLRenderer                      (                      )                      ;                      renderer.                      setSize                      (window.innerWidth,                      window.innerHeight)                      ;                      document.body.                      appendChild                      (renderer.domElement)                      ;                                      
    The first line creates a new renderer, the second line sets the size at which the renderer volition depict the camera'southward view, and the third line appends the <canvas> chemical element created by the renderer to the document's <body>. At present anything the renderer draws will exist displayed in our window.
  7. Next, we want to create the cube we'll display on the sail. Add together the following chunk of code at the bottom of your JavaScript:
                                              permit                      cube;                      const                      loader                      =                      new                      THREE.TextureLoader                      (                      )                      ;                      loader.                      load                      (                      'metal003.png'                      ,                      texture                      =>                      {                      texture.wrapS                      =                      3                      .RepeatWrapping;                      texture.wrapT                      =                      Three                      .RepeatWrapping;                      texture.echo.                      prepare                      (                      two                      ,                      2                      )                      ;                      const                      geometry                      =                      new                      Three.BoxGeometry                      (                      two.4                      ,                      two.4                      ,                      2.four                      )                      ;                      const                      material                      =                      new                      THREE.MeshLambertMaterial                      (                      {                      map                      :                      texture                      }                      )                      ;                      cube                      =                      new                      THREE.Mesh                      (geometry,                      material)                      ;                      scene.                      add                      (cube)                      ;                      describe                      (                      )                      ;                      }                      )                      ;                                      
    In that location's a bit more to take in here, so let's go through information technology in stages:
    • We starting time create a cube global variable and then nosotros can access our cube from anywhere in the lawmaking.
    • Adjacent, we create a new TextureLoader object, and so phone call load() on it. load() takes ii parameters in this case (although information technology tin accept more): the texture nosotros desire to load (our PNG), and a function that will run when the texture has loaded.
    • Inside this role we apply properties of the texture object to specify that nosotros want a 2 x ii repeat of the image wrapped around all sides of the cube. Next, nosotros create a new BoxGeometry object and a new MeshLambertMaterial object, and bring them together in a Mesh to create our cube. An object typically requires a geometry (what shape it is) and a material (what its surface looks similar).
    • Terminal of all, we add our cube to the scene, then telephone call our depict() part to kickoff off the animation.
  8. Before we get to defining draw(), nosotros'll add a couple of lights to the scene, to liven things up a fleck; add the following blocks adjacent:
                                              const                      low-cal                      =                      new                      THREE.AmbientLight                      (                      'rgb(255,255,255)'                      )                      ;                      // soft white lite                      scene.                      add                      (light)                      ;                      const                      spotLight                      =                      new                      Iii.SpotLight                      (                      'rgb(255,255,255)'                      )                      ;                      spotLight.position.                      set                      (                      100                      ,                      1000                      ,                      m                      )                      ;                      spotLight.castShadow                      =                      true                      ;                      scene.                      add together                      (spotLight)                      ;                                      
    An AmbientLight object is a kind of soft lite that lightens the whole scene a fleck, like the dominicus when you are exterior. The SpotLight object, on the other paw, is a directional axle of calorie-free, more similar a flashlight/torch (or a spotlight, in fact).
  9. Final of all, let's add together our draw() function to the lesser of the code:
                                              office                      describe                      (                      )                      {                      cube.rotation.ten                      +=                      0.01                      ;                      cube.rotation.y                      +=                      0.01                      ;                      renderer.                      render                      (scene,                      camera)                      ;                      requestAnimationFrame                      (depict)                      ;                      }                                      
    This is fairly intuitive; on each frame, we rotate our cube slightly on its Ten and Y axes, then render the scene as viewed by our camera, and so finally telephone call requestAnimationFrame() to schedule drawing our side by side frame.

Let's take another quick look at what the finished product should look similar:

You can discover the finished code on GitHub.

Note: In our GitHub repo you tin can besides find another interesting 3D cube example — Three.js Video Cube (see it live also). This uses getUserMedia() to take a video stream from a computer spider web cam and project it onto the side of the cube as a texture!

Summary

At this indicate, you should take a useful idea of the basics of graphics programming using Sail and WebGL and what you tin do with these APIs, equally well as a good idea of where to go for farther information. Have fun!

Run into too

Here nosotros accept covered only the real basics of canvas — there is so much more to learn! The below articles will take yous further.

  • Canvas tutorial — A very detailed tutorial series explaining what you should know about second sheet in much more particular than was covered hither. Essential reading.
  • WebGL tutorial — A series that teaches the basics of raw WebGL programming.
  • Building upwards a basic demo with Iii.js — basic Iii.js tutorial. Nosotros also take equivalent guides for PlayCanvas or Babylon.js.
  • Game evolution — the landing page for web games development on MDN. At that place are some really useful tutorials and techniques available here related to 2D and 3D canvas — meet the Techniques and Tutorials menu options.

Examples

In this module

  • Introduction to web APIs
  • Manipulating documents
  • Fetching information from the server
  • Third party APIs
  • Drawing graphics
  • Video and audio APIs
  • Client-side storage

melaradayinkic.blogspot.com

Source: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics

Post a Comment for "Draw a Circle in Js"