Skip to content Skip to sidebar Skip to footer

draw 3d points from console firefox

Drawing graphics

Graphics on the Spider web

As nosotros talked about in our HTML Multimedia and embedding module, the Web was originally but text, which was very tedious, so images were introduced — first via the <img> element and afterward via CSS properties such as groundwork-paradigm, and SVG.

This however was still not enough. While y'all could apply CSS and JavaScript to breathing (and otherwise manipulate) SVG vector images — as they are represented past markup — there was still no way to do the aforementioned for bitmap images, and the tools available were rather limited. The Web still had no style to effectively create animations, games, 3D scenes, and other requirements commonly handled by lower level languages such as C++ or Java.

The situation started to improve when browsers began to support the <sail> element and associated Canvas API — Apple invented it in effectually 2004, and other browsers followed by implementing it in the years that followed. Equally you'll see below, sail provides many useful tools for creating second animations, games, data visualizations, and other types of app, peculiarly when combined with some of the other APIs the web platform provides.

The below case shows a simple 2D canvas-based billowy balls blitheness that we originally met in our Introducing JavaScript objects module:

Around 2006–2007, Mozilla started work on an experimental 3D canvas implementation. This became WebGL, which gained traction amongst browser vendors, and was standardized around 2009–2010. WebGL allows you to create real 3D graphics inside your web browser; the below instance shows a simple rotating WebGL cube:

This commodity will focus mainly on 2D sheet, equally raw WebGL code is very complex. We will however show how to use a WebGL library to create a 3D scene more easily, and y'all tin can find a tutorial roofing raw WebGL elsewhere — come across Getting started with WebGL.

Annotation: Basic sail functionality is supported well beyond browsers, with the exception of IE viii and below for second canvas, and IE 11 and beneath for WebGL.

Active learning: Getting started with a <sail>

If you want to create a 2D or 3D scene on a web page, you need to get-go with an HTML <canvas> chemical element. This chemical element is used to define the area on the page into which the image will be drawn. This is as unproblematic every bit including the element on the folio:

                                                                            <sail                    width                                          =                      "320"                                        height                                          =                      "240"                                        >                                                                              </canvas                    >                                                

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

Inside the canvas tags, yous can put some fallback content, which is shown if the user's browser doesn't support sail.

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

Of course, the above bulletin is really unhelpful! In a real example you'd want to relate the fallback content to the canvas content. For example, if you lot 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 sail

Let's start by creating our own canvas that we describe future experiments on to.

  1. First brand a local re-create of our 0_canvas_start.html file, and open up it in your text editor.
  2. Add the following code into information technology, simply below the opening <body> tag:
                                                                                                <canvas                        class                                                  =                          "myCanvas"                                                >                                                                                              <p                        >                      Add suitable fallback here.                                                  </p                        >                                                                                              </sheet                        >                                                            
    We have added a class to the <canvas> element and so information technology will be easier to select if we have multiple canvases on the folio, just we accept removed the width and height attributes for now (you could add them back in if you wanted, merely nosotros will set them using JavaScript in a below section). Canvases with no explicit width and height default to 300 pixels wide by 150 pixels high.
  3. Now add the following lines of JavaScript inside the <script> chemical element:
                                              const                      sail                      =                      certificate.                      querySelector                      (                      '.myCanvas'                      )                      ;                      const                      width                      =                      canvas.width                      =                      window.innerWidth;                      const                      superlative                      =                      canvass.tiptop                      =                      window.innerHeight;                                      
    Here nosotros take stored a reference to the canvas in the canvas constant. In the second line we set both a new constant width and the canvass' width holding equal to Window.innerWidth (which gives us the viewport width). In the third line we fix both a new abiding height and the canvas' height property equal to Window.innerHeight (which gives united states the viewport summit). So now nosotros have a canvas that fills the entire width and tiptop of the browser window! You'll also see that we are chaining assignments together with multiple equals signs — this is allowed in JavaScript, and it is a good technique if you want to make multiple variables all equal to the same value. We wanted to brand the canvas width and height easily accessible in the width/top variables, as they are useful values to have bachelor for afterwards (for example, if you want to draw something exactly halfway across the width of the canvas).
  4. If you save and load your example in a browser now, you lot'll see zip, which is fine, but you'll also encounter scrollbars — this is a trouble for united states, which happens because the <body> element has a margin that, added to our full-window-size canvas, results in a document that'south wider than the window. To get rid of the scrollbars, we need to remove the margin and likewise gear up overflow to hidden. Add together the following into the <head> of your document:
                                                                                                <style                        >                                                                                              torso                          {                          margin                          :                          0;                          overflow                          :                          subconscious;                          }                                                                                                                      </way                        >                                                            
    The scrollbars should at present be gone.

Note: You should generally set the size of the epitome using HTML attributes or DOM properties, as explained above. You could utilise CSS, just the problem and so is that the sizing is washed after the sail has rendered, and but like any other image (the rendered canvas is but an image), the image could become pixelated/distorted.

Getting the canvas context and final setup

We need to do one last affair before we tin consider our canvas template finished. To draw onto the canvas we demand to get a special reference to the cartoon surface area called a context. This is done using the HTMLCanvasElement.getContext() method, which for basic usage takes a unmarried string as a parameter representing the type of context you desire to retrieve.

In this case we desire a 2d canvass, and then add the post-obit JavaScript line below the others within the <script> chemical element:

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

Notation: other context values you lot could choose include webgl for WebGL, webgl2 for WebGL two, etc., but we won't demand those in this article.

Then that's it — our canvas is at present primed and fix for drawing on! The ctx variable now contains a CanvasRenderingContext2D object, and all drawing operations on the sheet will involve manipulating this object.

Let's do ane concluding thing earlier nosotros motion on. Nosotros'll colour the sail groundwork black to requite you a offset taste of the canvass API. Add the following lines at the lesser of your JavaScript:

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

Here nosotros are setting a fill color using the canvas' fillStyle property (this takes color values just like CSS properties exercise), and so drawing a rectangle that covers the entire area of the canvas with thefillRect method (the showtime two parameters are the coordinates of the rectangle's elevation left paw corner; the last ii are the width and superlative you lot want the rectangle drawn at — we told you those width and height variables would be useful)!

OK, our template is done and information technology's fourth dimension to move on.

2D canvass basics

Every bit we said above, all cartoon operations are done by manipulating a CanvasRenderingContext2D object (in our example, ctx). Many operations need to exist given coordinates to pinpoint exactly where to draw something — the peak left of the sheet is point (0, 0), the horizontal (x) centrality runs from left to right, and the vertical (y) centrality runs from meridian to bottom.

Cartoon shapes tends to be done using the rectangle shape primitive, or past tracing a line along a certain path and so filling in the shape. Below nosotros'll show how to do both.

Simple rectangles

Let's get-go with some simple rectangles.

  1. First of all, have a copy of your newly coded canvas template (or make a local re-create of 1_canvas_template.html if y'all didn't follow the higher up steps).
  2. Adjacent, add together the following lines to the lesser of your JavaScript:
                        ctx.fillStyle                      =                      'rgb(255, 0, 0)'                      ;                      ctx.                      fillRect                      (                      l                      ,                      50                      ,                      100                      ,                      150                      )                      ;                                      
    If you save and refresh, you should see a red rectangle has appeared on your canvas. Its meridian left corner is 50 pixels abroad from the top and left of the canvas edge (as defined by the first two parameters), and information technology is 100 pixels wide and 150 pixels tall (as defined past the third and fourth parameters).
  3. Let's add another rectangle into the mix — a green one this time. Add the post-obit at the bottom of your JavaScript:
                        ctx.fillStyle                      =                      'rgb(0, 255, 0)'                      ;                      ctx.                      fillRect                      (                      75                      ,                      75                      ,                      100                      ,                      100                      )                      ;                                      
    Salve and refresh, and y'all'll see your new rectangle. This raises an important indicate: graphics operations like drawing rectangles, lines, and and then forth are performed in the order in which they occur. Think of it similar painting a wall, where each coat of paint overlaps and may even hide what's underneath. You can't practice anything to change this, and then you have to call back carefully about the lodge in which y'all draw the graphics.
  4. Note that yous can depict semi-transparent graphics by specifying a semi-transparent colour, for example by using rgba(). The a value defines what'south called the "alpha channel, " or the amount of transparency the color has. The higher its value, the more than it will obscure whatsoever'south behind it. Add the post-obit to your code:
                        ctx.fillStyle                      =                      'rgba(255, 0, 255, 0.75)'                      ;                      ctx.                      fillRect                      (                      25                      ,                      100                      ,                      175                      ,                      l                      )                      ;                                      
  5. Now try cartoon some more rectangles of your ain; have fun!

Strokes and line widths

So far we've looked at cartoon filled rectangles, just you can also draw rectangles that are just outlines (chosen strokes in graphic design). To ready the color y'all desire for your stroke, yous employ the strokeStyle property; drawing a stroke rectangle is done using strokeRect.

  1. Add together the following to the previous case, 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; y'all can conform the lineWidth property value to change this (it takes a number representing the number of pixels broad the stroke is). Add the following line in between the previous two lines:

Now you should see that your white outline has become much thicker! That'south it for now. At this indicate your example should look like this:

Drawing paths

If y'all want to draw anything more complex than a rectangle, you need to draw a path. Basically, this involves writing code to specify exactly what path the pen should movement along on your canvas to trace the shape you want to depict. Canvass includes functions for drawing directly lines, circles, Bézier curves, and more.

Allow's get-go the section off by making a fresh copy of our sail template (1_canvas_template.html), in which to draw the new example.

We'll be using some common methods and properties across all of the beneath sections:

  • beginPath() — start drawing a path at the indicate 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 point on the canvas, without recording or tracing the line; the pen "jumps" to the new position.
  • fill() — depict a filled shape by filling in the path you lot've traced and then far.
  • stroke() — draw an outline shape by drawing a stroke along the path you lot've drawn so far.
  • You can also use features like lineWidth and fillStyle/strokeStyle with paths as well as rectangles.

A typical, elementary path-cartoon operation would look something like so:

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

Drawing lines

Let'due south depict an equilateral triangle on the canvas.

  1. First of all, add the following helper function to the bottom of your lawmaking. This converts caste values to radians, which is useful because whenever you need to provide an angle value in JavaScript, information technology will almost e'er be in radians, simply humans usually think in degrees.
                                              role                      degToRad                      (                      degrees                      )                      {                      render                      degrees                      *                      Math.                      PI                      /                      180                      ;                      }                      ;                                      
  2. Next, start off your path by adding the following below your previous addition; here we set a color for our triangle, start drawing a path, and then move the pen to (50, 50) without cartoon annihilation. That'due south where nosotros'll first drawing our triangle.
                        ctx.fillStyle                      =                      'rgb(255, 0, 0)'                      ;                      ctx.                      beginPath                      (                      )                      ;                      ctx.                      moveTo                      (                      50                      ,                      50                      )                      ;                                      
  3. Now add the following lines at the lesser of your script:
                        ctx.                      lineTo                      (                      150                      ,                      50                      )                      ;                      let                      triHeight                      =                      50                      *                      Math.                      tan                      (                      degToRad                      (                      60                      )                      )                      ;                      ctx.                      lineTo                      (                      100                      ,                      50                      +triHeight)                      ;                      ctx.                      lineTo                      (                      50                      ,                      50                      )                      ;                      ctx.                      fill                      (                      )                      ;                                      
    Let's run through this in order: Commencement we draw a line across to (150, 50) — our path now goes 100 pixels to the correct along the x axis. 2d, we piece of work out the height of our equilateral triangle, using a chip of simple trigonometry. Basically, we are drawing the triangle pointing downward. The angles in an equilateral triangle are always 60 degrees; to work out the height we tin can carve up it down the centre into ii correct-angled triangles, which volition each have angles of xc degrees, sixty degrees, and xxx degrees. In terms of the sides:
    • The longest side is called the hypotenuse
    • The side next to the 60 caste angle is called the next — which we know is 50 pixels, as it is one-half of the line we just drew.
    • The side opposite the 60 degree bending is called the contrary, which is the height of the triangle nosotros want to summate.
    I of the basic trigonometric formulae states that the length of the next multiplied by the tangent of the angle is equal to the opposite, hence we come up with 50 * Math.tan(degToRad(60)). We use our degToRad() function to convert threescore degrees to radians, equally Math.tan() expects an input value in radians.
  4. With the tiptop calculated, nosotros draw another line to (100, fifty + triHeight). The X coordinate is simple; information technology must be halfway betwixt the previous two X values we set. The Y value on the other hand must exist 50 plus the triangle height, every bit nosotros know the peak of the triangle is l pixels from the elevation of the sail.
  5. The next line draws a line back to the starting point of the triangle.
  6. Terminal of all, we run ctx.fill() to end the path and fill in the shape.

Cartoon circles

Now let's await at how to draw a circumvolve in canvas. This is accomplished using the arc() method, which draws all or part of a circumvolve at a specified signal.

  1. Allow'due south add together an arc to our canvas — add the post-obit to the lesser of your lawmaking:
                        ctx.fillStyle                      =                      'rgb(0, 0, 255)'                      ;                      ctx.                      beginPath                      (                      )                      ;                      ctx.                      arc                      (                      150                      ,                      106                      ,                      50                      ,                      degToRad                      (                      0                      )                      ,                      degToRad                      (                      360                      )                      ,                      fake                      )                      ;                      ctx.                      fill up                      (                      )                      ;                                      
    arc() takes 6 parameters. The first two specify the position of the arc'due south center (X and Y, respectively). The third is the circle'south radius, the fourth and 5th are the start and finish angles at which to draw the circumvolve (so specifying 0 and 360 degrees gives us a full circle), and the sixth parameter defines whether the circle should be drawn counterclockwise (anticlockwise) or clockwise (false is clockwise).

    Annotation: 0 degrees is horizontally to the right.

  2. Let's effort adding some other arc:
                        ctx.fillStyle                      =                      'xanthous'                      ;                      ctx.                      beginPath                      (                      )                      ;                      ctx.                      arc                      (                      200                      ,                      106                      ,                      l                      ,                      degToRad                      (                      -                      45                      )                      ,                      degToRad                      (                      45                      )                      ,                      true                      )                      ;                      ctx.                      lineTo                      (                      200                      ,                      106                      )                      ;                      ctx.                      fill                      (                      )                      ;                                      
    The pattern here is very like, just with 2 differences:
    • We have set the last parameter of arc() to truthful, meaning that the arc is drawn counterclockwise, which means that even though the arc is specified as starting at -45 degrees and catastrophe at 45 degrees, we describe the arc around the 270 degrees non within this portion. If you were to alter true to simulated and so re-run the code, but the 90 degree slice of the circle would be drawn.
    • Before calling fill(), nosotros draw a line to the center of the circle. This means that nosotros get the rather nice Pac-Man-style cutout rendered. If you removed this line (endeavour information technology!) then re-ran the lawmaking, you lot'd get but an edge of the circumvolve chopped off between the start and end bespeak of the arc. This illustrates some other important point of the sheet — if yous endeavour to fill an incomplete path (i.due east. ane that is non closed), the browser fills in a direct line betwixt the start and end indicate and and so fills information technology in.

That's it for now; your concluding example should await like this:

Notation: To find out more than about advanced path cartoon features such as Bézier curves, cheque out our Drawing shapes with canvas tutorial.

Text

Canvas as well has features for drawing text. Let's explore these briefly. Get-go by making another fresh copy of our canvas template (1_canvas_template.html) in which to draw the new example.

Text is drawn using 2 methods:

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

Both of these accept three properties in their basic usage: the text string to draw and the X and Y coordinates of the point to commencement drawing the text at. This works out every bit the bottom left corner of the text box (literally, the box surrounding the text you lot depict), which might confuse yous as other drawing operations tend to start from the top left corner — behave this in mind.

There are also a number of backdrop to assistance control text rendering such as font, which lets you lot specify font family unit, size, etc. It takes equally its value the same syntax every bit the CSS font belongings.

Try adding the following block to the lesser of your JavaScript:

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

Here we draw ii lines of text, 1 outline and the other stroke. The concluding example should expect similar so:

Have a play and come across what you can come up up with! You can discover more information on the options available for canvas text at Drawing text.

Drawing images onto sheet

It is possible to render external images onto your sail. These tin exist simple images, frames from videos, or the content of other canvases. For the moment nosotros'll simply look at the instance of using some elementary images on our sail.

  1. Equally before, brand another fresh copy of our sheet template (1_canvas_template.html) in which to draw the new case. In this case y'all'll also need to salvage a re-create of our sample epitome — firefox.png — in the same directory. Images are fatigued onto canvass using the drawImage() method. The simplest version takes 3 parameters — a reference to the paradigm you desire to render, and the X and Y coordinates of the image'southward top left corner.
  2. Let'south start by getting an image source to embed in our canvas. Add the following lines to the bottom of your JavaScript:
                                              let                      image                      =                      new                      Epitome                      (                      )                      ;                      image.src                      =                      'firefox.png'                      ;                                      
    Here nosotros create a new HTMLImageElement object using the Image() constructor. The returned object is the same type as that which is returned when you catch a reference to an existing <img> element). We and so set its src aspect to equal our Firefox logo image. At this point, the browser starts loading the image.
  3. We could now try to embed the image using drawImage(), simply we need to make certain the image file has been loaded beginning, otherwise the code volition fail. We can achieve this using the onload issue handler, which will just exist invoked when the image has finished loading. Add the post-obit block below the previous ane:
                        image.                      onload                      =                      office                      (                      )                      {                      ctx.                      drawImage                      (image,                      50                      ,                      50                      )                      ;                      }                                      
    If y'all load your example in the browser now, you lot should come across the image embedded in the canvas.
  4. Merely at that place's more! What if we want to display only a role of the image, or to resize information technology? We tin can do both with the more circuitous version of drawImage(). Update your ctx.drawImage() line like so:
                        ctx.                      drawImage                      (image,                      20                      ,                      20                      ,                      185                      ,                      175                      ,                      50                      ,                      50                      ,                      185                      ,                      175                      )                      ;                                      
    • The first parameter is the paradigm reference, as before.
    • Parameters ii and iii define the coordinates of the top left corner of the area you want to cut out of the loaded image, relative to the top-left corner of the image itself. Nothing to the left of the first parameter or above the second will be drawn.
    • Parameters four and five define the width and height of the surface area we want to cutting out from the original image we loaded.
    • Parameters vi and seven define the coordinates at which you want to draw the meridian-left corner of the cut-out portion of the image, relative to the height-left corner of the sail.
    • Parameters viii and 9 ascertain the width and height to depict the cut-out area of the prototype. In this case, we have specified the same dimensions as the original slice, merely you could resize it by specifying dissimilar values.

The concluding example should look like so:

Loops and animations

We have so far covered some very basic uses of 2D canvas, but really you won't feel the full power of canvas unless you update or breathing it in some way. Later on all, sail does provide scriptable images! If you aren't going to change annihilation, then you might equally well just apply static images and save yourself all the work.

Creating a loop

Playing with loops in canvas is rather fun — y'all can run canvas commands within a for (or other type of) loop just similar any other JavaScript code.

Let's build a unproblematic example.

  1. Brand another fresh copy of our canvas template (1_canvas_template.html) and open information technology in your lawmaking editor.
  2. Add the following line to the bottom of your JavaScript. This contains a new method, translate(), which moves the origin point of the canvas:
                        ctx.                      interpret                      (width/                      2                      ,                      elevation/                      ii                      )                      ;                                      
    This causes the coordinate origin (0, 0) to be moved to the center of the canvas, rather than being at the top left corner. This is very useful in many situations, like this one, where we want our design to be drawn relative to the middle of the canvas.
  3. Now add the following lawmaking to the lesser of the JavaScript:
                                              function                      degToRad                      (                      degrees                      )                      {                      return                      degrees                      *                      Math.                      PI                      /                      180                      ;                      }                      ;                      function                      rand                      (                      min,                        max                      )                      {                      return                      Math.                      flooring                      (Math.                      random                      (                      )                      *                      (max-min+                      1                      )                      )                      +                      (min)                      ;                      }                      let                      length                      =                      250                      ;                      let                      moveOffset                      =                      twenty                      ;                      for                      (                      var                      i                      =                      0                      ;                      i                      <                      length;                      i++                      )                      {                      }                                      
    Hither we are implementing the same degToRad() role we saw in the triangle case above, a rand() part that returns a random number betwixt given lower and upper bounds, length and moveOffset variables (which we'll find out more about afterward), and an empty for loop.
  4. The idea here is that we'll draw something on the canvas within the for loop, and iterate on information technology each time and so we tin can create something interesting. Add together the following code inside your for loop:
                        ctx.fillStyle                      =                      'rgba('                      +                      (                      255                      -length)                      +                      ', 0, '                      +                      (                      255                      -length)                      +                      ', 0.nine)'                      ;                      ctx.                      beginPath                      (                      )                      ;                      ctx.                      moveTo                      (moveOffset,                      moveOffset)                      ;                      ctx.                      lineTo                      (moveOffset+length,                      moveOffset)                      ;                      let                      triHeight                      =                      length/                      ii                      *                      Math.                      tan                      (                      degToRad                      (                      60                      )                      )                      ;                      ctx.                      lineTo                      (moveOffset+                      (length/                      2                      )                      ,                      moveOffset+triHeight)                      ;                      ctx.                      lineTo                      (moveOffset,                      moveOffset)                      ;                      ctx.                      fill up                      (                      )                      ;                      length--                      ;                      moveOffset                      +=                      0.7                      ;                      ctx.                      rotate                      (                      degToRad                      (                      5                      )                      )                      ;                                      
    So on each iteration, we:
    • Set the fillStyle to be a shade of slightly transparent purple, which changes each time based on the value of length. As yous'll run into later the length gets smaller each time the loop runs, so the effect hither is that the color gets brighter with each successive triangle drawn.
    • Begin the path.
    • Move the pen to a coordinate of (moveOffset, moveOffset); This variable defines how far we want to move each time we draw a new triangle.
    • Describe a line to a coordinate of (moveOffset+length, moveOffset). This draws a line of length length parallel to the X centrality.
    • Calculate the triangle's top, as before.
    • Draw a line to the down-pointing corner of the triangle, then describe a line dorsum to the start of the triangle.
    • Call fill() to fill in the triangle.
    • Update the variables that describe the sequence of triangles, so we can be ready to draw the next one. Nosotros subtract the length value by 1, so the triangles go smaller each fourth dimension; increase moveOffset past a small amount and then each successive triangle is slightly farther away, and use some other new function, rotate(), which allows the states to rotate the entire sail! We rotate information technology by 5 degrees earlier drawing the next triangle.

That's it! The concluding example should look like so:

At this signal, we'd similar to encourage you lot to play with the example and brand information technology your own! For example:

  • Draw rectangles or arcs instead of triangles, or fifty-fifty embed images.
  • Play with the length and moveOffset values.
  • Innovate some random numbers using that rand() role nosotros included in a higher place merely didn't use.

Animations

The loop instance we built higher up was fun, but really you need a constant loop that keeps going and going for any serious canvass applications (such as games and real time visualizations). If you lot think of your sheet as beingness like a picture show, you really want the display to update on each frame to show the updated view, with an ideal refresh charge per unit of sixty frames per 2nd so that movement appears nice and smooth to the human eye.

There are a few JavaScript functions that will permit yous to run functions repeatedly, several times a second, the all-time 1 for our purposes hither being window.requestAnimationFrame(). It takes one parameter — the proper name of the function you want to run for each frame. The next fourth dimension the browser is gear up to update the screen, your function will get called. If that part draws the new update to your animation, then calls requestAnimationFrame() again just before the end of the function, the animation loop will keep to run. The loop ends when yous stop calling requestAnimationFrame() or if you call window.cancelAnimationFrame() subsequently calling requestAnimationFrame() but before the frame is called.

Annotation: It's adept practice to call cancelAnimationFrame() from your principal code when y'all're done using the animation, to ensure that no updates are notwithstanding waiting to exist run.

The browser works out complex details such as making the animation run at a consistent speed, and non wasting resources animating things that can't be seen.

To see how it works, let's rapidly look again at our Bouncing Balls instance (see it live, and also see the source code). The code for the loop that keeps everything moving looks similar this:

                                  function                  loop                  (                  )                  {                  ctx.fillStyle                  =                  'rgba(0, 0, 0, 0.25)'                  ;                  ctx.                  fillRect                  (                  0                  ,                  0                  ,                  width,                  pinnacle)                  ;                  for                  (                  permit                  i                  =                  0                  ;                  i                  <                  balls.length;                  i++                  )                  {                  assurance[i]                  .                  describe                  (                  )                  ;                  assurance[i]                  .                  update                  (                  )                  ;                  balls[i]                  .                  collisionDetect                  (                  )                  ;                  }                  requestAnimationFrame                  (loop)                  ;                  }                  loop                  (                  )                  ;                              

We run the loop() part one time at the bottom of the lawmaking to start the bike, drawing the outset animation frame; the loop() function then takes charge of calling requestAnimationFrame(loop) to run the next frame of the animation, again and once more.

Notation that on each frame we are completely clearing the canvas and redrawing everything. For every ball nowadays we draw information technology, update its position, and cheque to see if it is colliding with whatever other assurance. In one case y'all've drawn a graphic to a canvas, there'south no way to manipulate that graphic individually like you can with DOM elements. You can't motility each ball effectually on the canvas, considering once information technology'south drawn, it'south part of the sail, and is not an individual accessible element or object. Instead, you have to erase and redraw, either by erasing the entire frame and redrawing everything, or by having lawmaking that knows exactly what parts demand to be erased and but 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 nosotros need for our case, though!

In general, the procedure of doing a sail animation involves the post-obit steps:

  1. Clear the canvas contents (due east.g. with fillRect() or clearRect()).
  2. Save land (if necessary) using salve() — this is needed when you want to salvage settings you've updated on the canvas before standing, which is useful for more than avant-garde applications.
  3. Draw the graphics you are animating.
  4. Restore the settings you saved in step 2, using restore()
  5. Call requestAnimationFrame() to schedule drawing of the next frame of the animation.

Notation: We won't cover save() and restore() hither, merely they are explained nicely in our Transformations tutorial (and the ones that follow information technology).

A simple graphic symbol animation

Now let's create our ain unproblematic animation — we'll get a character from a certain rather awesome retro computer game to walk across the screen.

  1. Brand another fresh copy of our canvas template (1_canvas_template.html) and open up it in your code editor. Make a copy of walk-right.png in the same directory.
  2. At the bottom of the JavaScript, add the post-obit line to once over again brand the coordinate origin sit in the middle of the canvas:
                        ctx.                      translate                      (width/                      2                      ,                      pinnacle/                      ii                      )                      ;                                      
  3. Now allow's create a new HTMLImageElement object, set its src to the image we desire to load, and add an onload issue handler that will cause the depict() function to fire when the image is loaded:
                                              let                      paradigm                      =                      new                      Epitome                      (                      )                      ;                      image.src                      =                      'walk-right.png'                      ;                      image.onload                      =                      describe;                                      
  4. Now we'll add together some variables to keep track of the position the sprite is to be fatigued on the screen, and the sprite number we want to brandish.
                                              let                      sprite                      =                      0                      ;                      let                      posX                      =                      0                      ;                                      
    Let'south explicate the spritesheet prototype (which nosotros have respectfully borrowed from Mike Thomas' Create a sprite sheet walk bike using CSS animation). The image looks like this: It contains six sprites that make up the whole walking sequence — each ane is 102 pixels wide and 148 pixels high. To display each sprite cleanly nosotros volition have to use drawImage() to chop out a unmarried sprite epitome from the spritesheet and display just that part, like we did above with the Firefox logo. The X coordinate of the slice will have to be a multiple of 102, and the Y coordinate will e'er exist 0. The slice size volition e'er be 102 by 148 pixels.
  5. Now let's insert an empty draw() role at the bottom of the code, ready for filling upward with some code:
  6. The rest of the code in this section goes inside depict(). Showtime, add the post-obit line, which clears the canvas to gear up for drawing each frame. Find that we have to specify the top-left corner of the rectangle as -(width/2), -(height/ii) because we specified the origin position equally width/2, height/ii earlier on.
                        ctx.                      fillRect                      (                      -                      (width/                      2                      )                      ,                      -                      (height/                      two                      )                      ,                      width,                      acme)                      ;                                      
  7. Next, nosotros'll describe our image using drawImage — the ix-parameter version. Add the following:
                        ctx.                      drawImage                      (image,                      (sprite*                      102                      )                      ,                      0                      ,                      102                      ,                      148                      ,                      0                      +posX,                      -                      74                      ,                      102                      ,                      148                      )                      ;                                      
    Every bit you tin can run across:
    • We specify paradigm equally the paradigm to embed.
    • Parameters 2 and 3 specify the summit-left corner of the slice to cut out of the source image, with the 10 value every bit sprite multiplied past 102 (where sprite is the sprite number between 0 and v) 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 half-dozen and seven specify the top-left corner of the box into which to draw the slice on the canvas — the 10 position is 0 + posX, meaning that nosotros tin can change the drawing position by altering the posX value.
    • Parameters 8 and nine specify the size of the image on the canvas. We just want to proceed its original size, so we specify 102 and 148 as the width and elevation.
  8. Now we'll change the sprite value later on each draw — well, later on some of them anyway. Add the post-obit block to the bottom of the draw() function:
                                              if                      (posX                      %                      13                      ===                      0                      )                      {                      if                      (sprite                      ===                      5                      )                      {                      sprite                      =                      0                      ;                      }                      else                      {                      sprite++                      ;                      }                      }                                      
    We are wrapping the whole block in if (posX % 13 === 0) { ... }. We utilize the modulo (%) operator (also known as the balance operator) to check whether the posX value can exist exactly divided by 13 with no balance. If so, we move on to the side by side sprite past incrementing sprite (wrapping to 0 later on we're done with sprite #5). This effectively ways that we are only updating the sprite on every 13th frame, or roughly almost 5 frames a 2d (requestAnimationFrame() calls u.s.a. at upwardly to 60 frames per 2nd if possible). We are deliberately slowing down the frame rate because nosotros only accept vi sprites to work with, and if we display one every 60th of a second, our character will move style too fast! Inside the outer block we use an if ... else statement to check 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 terminal sprite already, we reset sprite back to 0; if not we merely increment it past 1.
  9. Side by side nosotros need to work out how to change the posX value on each frame — add the post-obit lawmaking block but below your last 1.
                                              if                      (posX                      >                      width/                      2                      )                      {                      newStartPos                      =                      -                      (                      (width/                      2                      )                      +                      102                      )                      ;                      posX                      =                      Math.                      ceil                      (newStartPos)                      ;                      console.                      log                      (posX)                      ;                      }                      else                      {                      posX                      +=                      2                      ;                      }                                      
    We are using another if ... else statement to meet if the value of posX has go greater than width/2, which means our character has walked off the correct edge of the screen. If so, nosotros calculate a position that would put the grapheme just to the left of the left side of the screen. If our character hasn't even so walked off the edge of the screen, we increment posX by 2. This volition brand him move a fiddling bit to the right the adjacent fourth dimension we draw him.
  10. Finally, nosotros demand to brand the blitheness loop by calling requestAnimationFrame() at the lesser of the draw() function:
                        window.                      requestAnimationFrame                      (depict)                      ;                                      

That'south it! The final case should look similar so:

A unproblematic drawing application

As a last animation example, nosotros'd like to evidence you lot a very elementary drawing application, to illustrate how the animation loop can be combined with user input (similar mouse movement, in this case). Nosotros won't get y'all to walk through and build this 1; we'll only explore the near interesting parts of the lawmaking.

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

Let'due south look at the most interesting parts. Start of all, we keep track of the mouse's X and Y coordinates and whether information technology is being clicked or not with three variables: curX, curY, and pressed. When the mouse moves, nosotros fire a function set equally the onmousemove event handler, which captures the current 10 and Y values. Nosotros as well use onmousedown and onmouseup event handlers to change the value of pressed to true when the mouse push button is pressed, and back to false once again when it is released.

                                  let                  curX;                  allow                  curY;                  let                  pressed                  =                  false                  ;                  document.                  onmousemove                  =                  function                  (                  e                  )                  {                  curX                  =                  (window.Consequence)                  ?                  eastward.pageX                  :                  e.clientX                  +                  (document.documentElement.scrollLeft                  ?                  document.documentElement.scrollLeft                  :                  document.body.scrollLeft)                  ;                  curY                  =                  (window.Event)                  ?                  eastward.pageY                  :                  e.clientY                  +                  (certificate.documentElement.scrollTop                  ?                  document.documentElement.scrollTop                  :                  document.body.scrollTop)                  ;                  }                  canvas.                  onmousedown                  =                  part                  (                  )                  {                  pressed                  =                  truthful                  ;                  }                  ;                  canvas.                  onmouseup                  =                  function                  (                  )                  {                  pressed                  =                  false                  ;                  }                              

When the "Articulate canvas" push button is pressed, we run a simple role that clears the whole canvas back to black, the aforementioned way nosotros've seen before:

                clearBtn.                  onclick                  =                  role                  (                  )                  {                  ctx.fillStyle                  =                  'rgb(0, 0, 0)'                  ;                  ctx.                  fillRect                  (                  0                  ,                  0                  ,                  width,                  pinnacle)                  ;                  }                              

The cartoon loop is pretty elementary this time effectually — if pressed is true, we draw a circle with a fill manner equal to the value in the color picker, and a radius equal to the value set in the range input. We have to depict the circle 85 pixels higher up where we measured it from, because the vertical measurement is taken from the peak of the viewport, but nosotros are cartoon the circle relative to the summit of the canvas, which starts below 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                  )                  ,                  false                  )                  ;                  ctx.                  fill                  (                  )                  ;                  }                  requestAnimationFrame                  (draw)                  ;                  }                  draw                  (                  )                  ;                              

Note: The <input> range and color types are supported fairly well across browsers, with the exception of Net Explorer versions less than ten; as well Safari doesn't nevertheless support color. If your browser doesn't support these inputs, they volition autumn back to simple text fields and you'll just have to enter valid color/number values yourself.

WebGL

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

WebGL is based on OpenGL (Open Graphics Library), and allows you to communicate straight with the reckoner's GPU. As such, writing raw WebGL is closer to low level languages such equally C++ than regular JavaScript; it is quite complex but incredibly powerful.

Using a library

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

Yes, using one of these means learning some other new API (a 3rd political party one, in this case), only they are a lot simpler than coding raw WebGL.

Recreating our cube

Let's wait at a simple instance of how to create something with a WebGL library. Nosotros'll choose Iii.js, equally it is 1 of the nigh pop ones. In this tutorial nosotros'll create the 3D spinning cube nosotros saw before.

  1. To outset with, make a local copy of alphabetize.html in a new folder, so relieve a copy of metal003.png in the aforementioned binder. This is the paradigm we'll utilise as a surface texture for the cube afterward.
  2. Next, create a new file called main.js, again in the aforementioned folder as before.
  3. If you open up index.html in your code editor, yous'll encounter that it has two <script> elements — the starting time one attaching three.min.js to the page, and the second ane attaching our main.js file to the page. You lot need to download the three.min.js library and save it in the same directory every bit earlier.
  4. Now we've got three.js attached to our page, we tin start to write JavaScript that makes use of it into main.js. Let's start past creating a new scene — add the following into your chief.js file:
                                              const                      scene                      =                      new                      3.Scene                      (                      )                      ;                                      
    The Scene() constructor creates a new scene, which represents the whole 3D earth we are trying to brandish.
  5. Next, nosotros need a camera so nosotros tin can run into 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.1                      ,                      1000                      )                      ;                      photographic camera.position.z                      =                      5                      ;                                      
    The PerspectiveCamera() constructor takes four arguments:
    • The field of view: How wide the area in forepart of the camera is that should be visible onscreen, in degrees.
    • The aspect ratio: Usually, this is the ratio of the scene's width divided by the scene'southward tiptop. Using another value will distort the scene (which might exist what y'all want, only unremarkably isn't).
    • The near airplane: How shut to the camera objects can exist before we stop rendering them to the screen. Think nigh how when you move your fingertip closer and closer to the space between your optics, eventually you can't encounter it anymore.
    • The far airplane: How far away things are from the camera before they are no longer rendered.
    Nosotros also set the camera'due south position to be v distance units out of the Z axis, which, like in CSS, is out of the screen towards y'all, the viewer.
  6. The third vital ingredient is a renderer. This is an object that renders a given scene, as viewed through a given photographic camera. We'll create one for at present using the WebGLRenderer() constructor, but we'll non use it till later. Add the post-obit lines next:
                                              const                      renderer                      =                      new                      3.WebGLRenderer                      (                      )                      ;                      renderer.                      setSize                      (window.innerWidth,                      window.innerHeight)                      ;                      document.body.                      appendChild                      (renderer.domElement)                      ;                                      
    The beginning line creates a new renderer, the 2nd line sets the size at which the renderer will describe the camera'southward view, and the third line appends the <canvas> element created by the renderer to the document'southward <body>. Now annihilation the renderer draws will be displayed in our window.
  7. Next, we want to create the cube we'll display on the sail. Add together the following clamper of code at the bottom of your JavaScript:
                                              let                      cube;                      let                      loader                      =                      new                      THREE.TextureLoader                      (                      )                      ;                      loader.                      load                      (                      'metal003.png'                      ,                      function                      (                      texture                      )                      {                      texture.wrapS                      =                      THREE                      .RepeatWrapping;                      texture.wrapT                      =                      THREE                      .RepeatWrapping;                      texture.repeat.                      gear up                      (                      2                      ,                      2                      )                      ;                      permit                      geometry                      =                      new                      Iii.BoxGeometry                      (                      2.4                      ,                      2.4                      ,                      2.4                      )                      ;                      let                      material                      =                      new                      THREE.MeshLambertMaterial                      (                      {                      map                      :                      texture,                      shading                      :                      THREE                      .FlatShading                      }                      )                      ;                      cube                      =                      new                      THREE.Mesh                      (geometry,                      material)                      ;                      scene.                      add                      (cube)                      ;                      draw                      (                      )                      ;                      }                      )                      ;                                      
    There's a chip more to have in hither, and so let's go through it in stages:
    • We first create a cube global variable and then we tin can access our cube from anywhere in the code.
    • Next, we create a new TextureLoader object, then phone call load() on information technology. load() takes two parameters in this case (although it tin accept more): the texture we desire to load (our PNG), and a function that volition run when the texture has loaded.
    • Within this role nosotros use backdrop of the texture object to specify that nosotros want a 2 x 2 repeat of the image wrapped around all sides of the cube. Next, we 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 like).
    • Last of all, we add our cube to the scene, then call our draw() function to start off the animation.
  8. Before we get to defining describe(), we'll add a couple of lights to the scene, to liven things up a bit; add the following blocks next:
                                              permit                      light                      =                      new                      THREE.AmbientLight                      (                      'rgb(255, 255, 255)'                      )                      ;                      // soft white calorie-free                      scene.                      add                      (light)                      ;                      allow                      spotLight                      =                      new                      THREE.SpotLight                      (                      'rgb(255, 255, 255)'                      )                      ;                      spotLight.position.                      set                      (                      100                      ,                      thousand                      ,                      grand                      )                      ;                      spotLight.castShadow                      =                      truthful                      ;                      scene.                      add together                      (spotLight)                      ;                                      
    An AmbientLight object is a kind of soft light that lightens the whole scene a bit, like the sun when you are outside. The SpotLight object, on the other paw, is a directional beam of calorie-free, more like a flashlight/torch (or a spotlight, in fact).
  9. Last of all, let'south add together our draw() role to the bottom of the code:
                                              function                      draw                      (                      )                      {                      cube.rotation.10                      +=                      0.01                      ;                      cube.rotation.y                      +=                      0.01                      ;                      renderer.                      render                      (scene,                      camera)                      ;                      requestAnimationFrame                      (draw)                      ;                      }                                      
    This is fairly intuitive; on each frame, we rotate our cube slightly on its X and Y axes, then return the scene as viewed past our camera, then finally call requestAnimationFrame() to schedule drawing our adjacent frame.

Let's have some other quick expect at what the finished product should look like:

You tin notice the finished lawmaking on GitHub.

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

Summary

At this point, yous should have a useful idea of the basics of graphics programming using Sheet and WebGL and what you can do with these APIs, as well every bit a expert idea of where to go for further data. Have fun!

Run across likewise

Here nosotros have covered only the existent basics of canvas — there is then much more than to acquire! The below articles will take you lot further.

  • Canvas tutorial — A very detailed tutorial series explaining what y'all should know most 2nd sail in much more particular than was covered hither. Essential reading.
  • WebGL tutorial — A serial that teaches the basics of raw WebGL programming.
  • Building up a bones demo with Three.js — bones 3.js tutorial. We also have equivalent guides for PlayCanvas or Babylon.js.
  • Game development — the landing page for spider web games evolution on MDN. There are some actually useful tutorials and techniques available here related to second and 3D canvas — meet the Techniques and Tutorials carte options.

Examples

In this module

  • Introduction to web APIs
  • Manipulating documents
  • Fetching data from the server
  • Tertiary party APIs
  • Cartoon graphics
  • Video and audio APIs
  • Client-side storage

hopewartn1965.blogspot.com

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

Post a Comment for "draw 3d points from console firefox"