Wait/Loading Animation Vectors |
|||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|||||||||||||||||||||
Tutorial:
|
|
||||||||||||||||||||
The last tutorial covered the basics of drawing on a Browser Canvas using an Unsigned Unit Interval [0,1]. This beginning will now be extended to draw a circular shading over the canvas.
The following picture is drawn, it is not a downloaded html image: As with all of these tutorial pages, you can see how the image is drawn simply by viewing the source for this page on your browser.
The radius and middle of the circle need to be specified. For these tutorials, the middle of a square canvas will be used for simplicity. At the moment, the radius won't be used: this page is developing a shading over the whole canvas which will be made circular in the next tutorial.
Imagine a line from the middle of the circle to the pixel currently being drawn. dx and dy will now be describing that line as its vector components.
The fastest way to make a circular shading is using the dot product between two vectors.
Be sure to check out that link to the dot product because the interactive image is created using the same procedural techniques that are used for this animation!
If they are Unit Vectors, the result will be a Signed Unit Interval [-1,1] which is in keeping with the system used here. Converting from Signed to Unsigned Unit Intervals and back again is easily achieved with the following two functions:// Minimise mapping by having everything return normalised ranges [0,1] or [-1,1]. // Unsigned Interval is [0,1]; Signed interval is [-1,1]; These change between the two (useful for double or float): function Signed(t) {return 2*t-1;} // Turn an Unsigned Unit Interval [0,1] into a Signed Unit Interval [-1,1] function Unsigned(t) {return (t+1)/2.0;} // Turn a Signed Unit Interval [-1,-1] into an Unsigned Unit Interval [0,1]The Vector Dot Product is wonderfully quick to calculate and will give answers we can easily use, but it needs two vectors and there is only one so far! A Wait/Loading animation spins, so the other vector will be spinning. For now any Unit Vector will do and will be represented with an 's' prefix for 'spinning': (sdx,sdy). For the moment the vector (0,-1) will be simple and natural looking, drawing white from the middle to the top, black from the middle to the bottom and smoothly shading around the mid-point; looking like the view of a cone from the point, lit from above:
Using the vector (0,-1) reduces the dot product equation from dx*sdy + dy*sdx to -dy. To make the result a unit vector it is divided by the distance, which is the hypotenuse of (dx,dy):
// Return the hypotenuse, standard distance function across cartesian x and y. function Math.hypot(x,y) {return Math.sqrt(x*x+y*y);}Since this Distance can be zero, a division by zero is possible and that'll happen when drawing the middle pixel. It doesn't really matter what shade the middle pixel is. Here it'll be set mid-grey (0.5) like the rest of the middle row, as shown (the 0.5):var Radius=25; // The canvas is 50 pixels square var xMid=Radius; // The middle of the circle - also the middle of the canvas square in these examples: var yMid=Radius; for(var y=c.height; y--;) { var dy=y-yMid; // vector from control's middle to current point being drawn for(var x=c.width; x--;) { var dx=x-xMid; // vector from control's middle to current point being drawn var Distance=Math.hypot(dx,dy); // Distance from Middle of circle to point being drawn var t=Distance ? Unsigned(-dy/Distance) : 0.5; // unit Dot Product using (0,-1) as the second vectorNow that there is circular shading, it needs to be in a circle! An antialiased circular outline will be developed in the next tutorial.