Page Contents | Comments |
---|---|

Images on Canvas and Perspective | Image and canvas aspect ratio, resizing the canvas dynamically, perspective, images as animation backgrounds |

Three Dimensional Drawings and Animations | Perspective, vanishing points, 3D cubes, cubes in motion, the perception of 3D motion on canvas |

Animating Ellipses | Drawing and animating ellipses, morphing ellipses, introduction to the theory of the ellipse |

Ellipses in Motion | An ellipse moving towards and away from you- motion paths, the perception of 3D motion on canvas |

Polygons and Stars | Functions for drawing polygons and stars: a rotating star, meshing rotating stars |

Polynomials | Using polynomials to create curved motion paths, parabolas and cubic polynomials, a hexagon in motion |

This image is an *enlarged part* of the original image of the Roman Forum

It has been placed on the canvas using- *drawImage(imageID,sX,sY,sW,sH,canX,canY,canImgWidth,canImgHeight)*

The original image has been cropped to display only the part of it we wish to see.

This causes the image on canvas to be enlarged.

The aspect ratio of the cropped image on canvas has been set to the aspect ratio of the original image.

sX, sY are the coordinates of the image we wish to enlarge.

sW, sH are the width and height on the image we wish to enlarge.

The rest of the variables used in drawImage() have the same values as those in Figure 1/Frame 1

The aspect ratio of the Shard image is completely different than that of the Roman Forum

The *aspect ratio* of an image=width/height.

The size of the original image of the Roman Forum is width=1600px, height=1200px, its aspect ratio=1600/1200=1.333333'.

The canvas width for the Roman Forum was set to 500px, so the canvas height=500/1.33333=375px.

The size of the original image of the Shard is width=1200px, height =1600px, its aspect ratio=1200/1600=0.75.

The canvas width for the Shard was set to 350px, the canvas height=350/0.75=466px

Using the same aspect ratio for the original and canvas images ensures they are both proportioned the same.

The red lines drawn along the tops of the windows of the building are lines of perspective.

The lines of perspective for the top row of windows are converging to a vanishing point.

The same applies to the bottom row of windows, they converge to a different vanishing point.

The length of the vertical sides of the windows get shorter, the further away they are.

Horizontal lines converge and vertical lines get shorter: at the vanishing point, horizontals meet; verticals become zero.

Some horizontal lines of perspective have been coloured red and the verticals between them can be seen to shorten.

The two figures in the image can be made out as women, but we can tell they are some distance away, their features cannot be seen

In the doorway behind the women, other figures can just be made out.

Each frame for Figure 1 has descriptive text associated with it, which is enclosed within div tags.

This is the text you are reading.

Changing the canvas dimensions requires the width and height of the div tag to be recalculated.

This has been done using Javascript.

The scene is a well known view in Melbourne, Australia.

The width of the div tag associated with the canvas has been calculated and the div height has been set to the canvas height, using javaScript.

Two lines of perspective have been shown in red. Sometimes lines of perspective are hidden behind objects.

Each of the lines of perspective have a vanishing point: numerous lines of perspective could be drawn for the building.

Two more lines of perspective are shown in blue, if they were extended further they would pass behind the statue.

The blue lines of perspective have their own vanishing point.

The figures near the building are more distant than the statue, their outlines are not distinct, the colour of their clothing appears dowdy.

The buttons that allow control of the canvas images must be processed each time the canvas size is changed and the user clicks one of them.

This processing is complex and requires the use of Javascript event listeners.

Each canvas on this web page must be processed in the same way, each has its own event listener, its own set of divs and its own buttons.

The Glass House Mountains are famous for their outstanding beauty.

The image elements that perspective can be applied to are the telegraph poles, the one that is farthest away is shorter.

Its shape is less distinct and its colour is not as deep as the one that is nearer.

The natural features of the image allow us to tell which are nearest to us.

The foliage of the shrub in the foreground is more distinct and greener than those on the mountain.

Elements of the image that are further away are sometimes behind those in front.

The mountain appears to be about 2.5 times higher than the nearest telegraph pole, in reality it is 235m high.

Clicking the Play button starts an animation. The ellipse could be any shape.

You can pause and replay the animation as often as you like.

The animation demonstrates that we can use images for the canvas background.

The ellipse appears to pass in front of the mountain.

Using images as the background of animations where appropriate is important.

To draw a complex background image is time consuming and difficult.

Taking a photograph, or using an existing image, takes a few minutes.

This is an image of the Roman Forum in Rome.

It has been placed on the canvas using the javaScript drawImage() method.

The syntax is: *context.drawImage(imageID,canX,canY,canImgWidth,canImgHeight)*

The image of the Roman Forum has been drawn using:

*context.drawImage(imageID,0,0,canWidth,dwgZoneHeight);*

canImgWidth=canWidth is the width of the canvas

canImgHeight=dwgZoneHeight is the area of the canvas allocated to drawings

The dwgZoneHeight excludes the height of the canvas allocated to the buttons.

The *image aspect ratio* on canvas is the same that of the of the original image.

Aspect ratio is explained in the following frames

The cube shown in the previous Frame is a jpeg image created in Microsoft Visio.

The three cubes drawn in this Frame have been drawn with a javaScript function called cuboid.

They could represent the outline shape of buildings, see the image of Melbourne in Figure 1.

The cubes share a common vanishing point that is off the right hand side of the canvas.

Horizontal lines converge, vertical lines shorten and colours become duller the further the cubes are from us.

The combined effect is that we perceive the cubes as 3 dimensional objects.

An example call of cuboid for cube C, the cube furthest from us is:

*var xS=350, yS=200, L1=80, L4=100, alpha=10, lw=2, lineCol='red', L5=60,
beta=5, fillCube=true, fAcol="#BB0000", fBcol="#AA0000", drawStrokes=false,
cubeC=shapes.cuboid(context,xS,yS,L1,L4,L5,alpha,beta,lw,lineCol,drawStrokes,fillCube,fAcol,fBcol);
*

Cuboid is versatile, and it is animateable.

A white box has been created using the cuboid function, it could represent a simple van.

The red boxes have been drawn with the cuboid function, they are not a jpeg image.

The horizontals of the van converge towards vanishing points and verticals get shorter.

As the van moves horizontals should get shorter and so should verticals.

The van colours should also get darker.

The perception of convergence of the van horizontals has been done by making it follow a line of motion.

The line of motion is parallel to the bottom horizontals of the cubes.

Shortening of the horizontals and verticals has been done by gradually reducing lengths of the van edges as it moves.

Making the van colours duller as it move has not been done: changing colour gradually will be demonstrated in the next frame.

The animation has been stopped when the leading vertical of the van reaches the trailing vertical of the last cube.

The "van" shown is the same shape as the white van in Frame 3 but it is larger.

Both shapes have the same aspect ratio.

The face colours have been made red and blue, and both colours will be made duller as the van moves.

Colours have been set using the rgb(red,green,blue) function,

Red has been set using red=rgb(250,0,0), blue has been set as blue=rgb(0,0,255).

In the code symbols have been used and colour components have been decremented as motion progresses.

A code snippet for the colours of face A of the "van", which is red is:

*
rA=255, gA=0,bA=0,this.rA=rA, this.gA=gA, this.bA=bA,
fAcol="rgb("+ this.rA +","+ this.gA +","+ this.bA +")";
delColA=1.0, delColB=1.0; this.rA=this.rA-delColA; this.bB=this.bB-delColB;
*

Animating colours is straightforward, but knowing how colours look at a distance is not.

A cube is a simple 3 dimensional shape with 6 faces.

We can never see all the faces at once, we can see 3 faces, 2 faces, or 1 face.

This is a property of 3 dimensional space and how we see.

The drawing of the cube shows 2 faces, if we were looking down on the cube, we would also see its top face.

Two vanishing points have been drawn on the canvas, vp1 and vp2.

To make the shape look 3 dimensional we make horizontal lines of the real cube appear to converge in the drawing.

Vertical lines of the real cube are made to shorten in the drawing.

The combined effect is that we perceive the drawing of the cube as 3 dimensional.

The vanishing points have x and y coordinates: vp1x,vp1y and vp2x,vp2y.

Both vanishing points have been drawn on the canvas: vanishing points can be outside the canvas.

This animation morphs an ellipse by decreasing its major axis gradually.

This makes the circle morph, that is, change into the familiar elliptical shape.

As the ellipse is morphed, it appears to rotate about its vertical axis.

This gives the impression that the ellipse is rotating in 3 dimensions.

The animation is stopped when the ellipse major axis reaches 10px.

The function ellipse has 30 lines of code and uses only basic javaScript defined functions.

Using javaScript basic defined functions ensures ellipse works with all major browsers.

The ellipse was tested using Chrome, Firefox, Safari and *Internet Explorer*.

When the javaScript predefined ellipse function was compared with our *shapes.ellipse* function the ellipses drawn were identical.

Press Play to run the animation.

This animation morphs an ellipse by decreasing its minor axis gradually.

This makes the circle morph, that is, change into the familiar elliptical shape.

As the ellipse is morphed, it appears to rotate about its horizontal axis.

This gives the impression that the ellipse is rotating in 3 dimensions.

The animation is stopped when the ellipse minor axis reaches 10px.

The use of customised functions to draw shapes in general can make them work for most major browsers.

The shapes can be made easy to use, versatile and animatable.

Properties of particular interest can be added, as we shall see when more animatable shapes, such as stars, are created.

When the ellipse morphs, the vertical axis shortens, to give a 3D effect.

The shortening of the vertical axis gives the impression the ellipse is rotating in 3 dimensions.

This ellipse has been drawn with an arc (stroke) but it has not been filled.

The ellipse has been animated by gradually reducing the vertical (minor) axis.

This gives the impression that ellipse is rotating in 3 dimensions.

The animation is stopped when the ellipse vertical axis reaches zero.

The ellipse morphs from a circle to a straight line.

Actually the "straight line" is really two lines:

one for the "top" of the ellipse, the other for the "bottom" of the ellipse.

The width of the line is 4px. The lines overlap, there is no gap between them.

The line width lw of the ellipse stroke is 3px, 2 line widths =6px, but the lines overlap to give a visible width of 4px.

We shall cover javaScript lines in later sections of this page.

The diagram shows the basic properties of an ellipse that were used in the function *shapes.ellipse*.

The parametric equations of the ellipse are:

$x=aX\cos (t)$, where aX is the ellipse semimajor axis.

$y=bY\sin (t)$, where bY is the ellipse semiminor axis.

t=is an angle between 0 and 360 degrees: we have called the angle t theta, in *shapes.ellipse*.

Calculations in javaScript must be in radians: the conversion from degrees to radians is done by *shapes.ellipse*.

xC is the x coordinate of the ellipse centre, relative to x=0, the left hand side of the canvas.

yC is the y coordinate of the ellipse centre, relative to y=0, the top of the canvas.

making theta < than 360 draws a part of an ellipse.

The ellipse can be made to rotate about is centre.

The ellipse stroke and fill can be set to any colour and both, or either, can be suppressed.

*shapes.ellipse* is versatile and animatable.

The circle shown is an ellipse drawn with the minor axis equal to the major axis.

The ellipse has been drawn with a customised function that works with any of the major browsers.

The function call for the circle shown is *ellipseA=shapes.ellipse(context,aX,bY,xC,yC,theta,lw,arcCol,fillEllipse,drawArc,fillCol,rotAng)*

context=the canvas context

aX=100px is the length of the ellipse major axis, bY=100px is the length of the ellipse minor axis.

xC=200px is the x coordinate of the ellipse centre, yC=150px the y coordinate of the ellipse centre.

theta=360 degrees the angle of the ellipse arc, theta less than 360 degrees draws only a portion of the ellipse.

lw=3px is the width of the ellipse stroke.

arcCol="blue" is the colour of the ellipse arc, fillEllipse=true, fills the ellipse, false does not fill the ellipse.

drawArc=true, draws the arc of the ellipse, false does not draw the ellipse arc, fillCol="red" is the colour of the ellipse fill.

rotAng= 0, means the ellipse will not be rotated about its centre, if rotAng is not zero, the ellipse can made to rotate about its center.

*The ellipse function is very versatile and animatable.*

The ellipse shape is maintained by keeping its aspect ratio the same as it "moves".

The blue ellipse is made to appear to move towards you by increasing its major and minor axes.

Again, the ellipse shape is maintained by keeping its aspect ratio the same as it "moves".

The quality of ellipses drawn on canvas depends upon their size and the pixel density of the display.

The blue ellipse is not as well formed as the larger yellow ellipse.

This helps to give the impression that the blue ellipse is further away from you.

Shape quality is important: we shall address it in the following sections of this page.

Shapes that are further away appear smaller, less well defined and colours are more dowdy.

Colours have not been made to appear dowdy in this demonstration.

There is now a strong impression that the yellow ellipse moves away from you and blue ellipse moves towards you.

The ellipses will be made to follow lines of motion, shown by the straight lines.

The ellipse centres will move along the lines of motion.

The equation for the line of motion for the yellow ellipse is $y=mx$, where m is the slope of the line.

The equation for the line of motion for the blue ellipse is $y=-mx$

Both ellipses have the same maximum and minimum major and minor axes.

The yellow ellipse is drawn before the blue ellipse.

This is important when the ellipses pass each other, the blue ellipse appears to pass in front of the yellow ellipse.

There is a lot of detail required to make the animation work.

Symmetry is used to reduce the amount of detail required.

The fact that one ellipse passes in front of the other reinforces the perception that they are moving in opposite directions.

The centres of the ellipses cross where their lines of motion intersect.

The large yellow ellipse is supposed to be nearer to you and the small blue ellipse is further away from you.

The ellipses have the same aspect ratio when they are stationary and when they are in motion.

We shall define the aspect ratio as (major axis)/(minor axis)=2aX/2bY=aX/bY

For the large ellipse aX=90 and bY=45 the aspect ratio =90/45=2

For the small ellipse aX=20 and bY=10 the aspect ratio =20/10=2

Both ellipses are the same shape even though they are different sizes.

The illusion of motion away from you is made by diminishing the yellow ellipse's major and minor axis.

The ellipse that is moving towards you has its major and minor axis increased.

Note that the smaller ellipse is not so well defined as the larger ellipse. This is because the canvas resolution is fixed at 1px.

The major axis of the larger ellipse is 180px, the major axis of the smaller ellipse is 40px.

The "quality" of the large ellipse is better than the quality of the small ellipse.

Ellipses with a minor axis less than 10px become distorted.

"butt" is the default value in most browsers, if you don't use a lineCap value, "butt" will be used.

context.lineCap="round" adds a semicircular round cap to the ends of a line.

This is demonstrated with the Group A lines: the line caps overlap.

context.lineCap="butt" does not add a cap to the lines, lines butt together.

The is demonstrated by the Group B lines- this group of lines have not used lineCap explicitly, the default has been applied.

The lines in Group C have been drawn using context.lineCap="square", the line endings are square and the line ends overlap.

The lines in Group D use lineCap="butt" explicitly, the lines butt together.

The lines in Group E have been made to touch by moving the blue line start by the diameter of the line cap.

context.lineCap="round" has been used to join all the lines, which ensures the line segments always overlap.

The function call to draw an octagon is:

var xC=200, yC=150, r=100, nS=8, lw=2, arcCol="blue", fillPoly=true, fillCol="red", rotAng=0,

poly01=shapes.polygon(context,xC,yC,r,nS,lw,arcCol,fillPoly,fillCol,rotAng);

The polygon is based on a circle of radius r and a number of sides nS.

The polygons drawn have nS=3,4,5,...to 13 for the blue polygon.

The large red polygon has nS=20, it closely resembles a circle.

The polygon can be made to morph into a circle by increasing the number of sides, nS.

The star shape is a regular polygon but it is constructed using two circles.

All outer sharp points of the star all lie on the circumference of an outer circle.

The points of the bottom of star arms lie on the circumference of an inner circle.

The call of

var xC=200,yC=160,r=50,R=150,nSp=8,lw=2,arcCol="blue",fillStar=true,fillCol="red",rotAng=30,

star01=window.shapes.stars(context,xC,yC,r,R,nSp,lw,arcCol,fillStar,fillCol,rotAng);

where: r=the radius of the inner, smaller circle.

R=the radius of the outer, larger circle.

nSp=the number of points on the star.

The quality of the star points is guaranteed by using lineCaps="round" on all the star points.

The function

The animation rotates the star by 360 degrees in steps of 2 degrees.

The stars are initialized as follows:

var xC=140,yC=160,r=50,R=100,nSp=8,lw=2,arcCol="blue",fillStar=true,fillCol="red",rotAng=0,delAng01=2,delAng02=2,

star01=window.shapes.stars(context,xC,yC,r,R,nSp,lw,arcCol,fillStar,fillCol,rotAng),

xC=xC+1.5*R,yC=yC-lw,rotAng=8,

star02=window.shapes.stars(context,xC,yC,r,R,nSp,lw,arcCol,fillStar,fillCol,rotAng);

this.rotAng01=0; //Initializes the rotation angle for star01

this.rotAng02=10; //Initializes the rotation angle for star02

The animation code for the stars is:

var clearCans=canvasOps.clearDwgZone(canvasID),

star01=window.shapes.stars(context,xC,yC,r,R,nSp,lw,arcCol,fillStar,fillCol,this.rotAng01);

this.rotAng01=this.rotAng01+delAng01;

var xC=xC+1.5*R,yC=yC-lw,

star02=window.shapes.stars(context,xC,yC,r,R,nSp,lw,arcCol,fillStar,fillCol,this.rotAng02);

this.rotAng02=this.rotAng02-delAng02;

Regular polygons have sides that are all the same length.

Polygons are closed shapes: a continuous path can traced following each line segment that terminates at the trace starting point.

There is no theoretical limit on the number of sides a polygon can have.

An ellipse is drawn using

All curved shapes, if they are closed or open, are drawn on the canvas using very

How straight lines join together affects the quality of shapes on the canvas.

The ends of the straight lines segemnts of the octagon have been drawn using the javaScript lineCap property.

The octagon has been drawn using the customised function called shapes.polygon

The parabola has been inverted by using: $y=-a{{x}^{2}}$

Many real objects, such as golf balls, military shells and jumping athletes follow an inverted parabolic path.

In fact the paths followed by these objects are not quite parabolic, due to friction.

The small black ball will follow the inverted parabolic path, moving from left to right.

The animation ends when the ball, which could be a golf ball, reaches the "ground".

To make the parabola fit on the canvas accurately the constant

The graph axes have not been shown in the animation.

The inverted parabolic motion path has not been drawn; it is still used as the motion path of the ball.

The green line shown in the animation could represent the "ground".

The blue path has been drawn using $y=a{{x}^{3}}$

The red path has been drawn using $y=-a{{x}^{3}}$

During the animation, the red ball will move along the red path.

The blue ball will move along the blue path.

The diameter of the red ball has been made slightly larger than that of the blue ball.

When the balls "pass" each other one will appear to pass in front of the other.

The paths have been fitted to the canvas and their shapes controlled by using: $a=ycMax/{{(xcMax)}^{3}}$

The motion paths have not been drawn in the animation.

The equation $y=a{{x}^{3}}+b{{x}^{2}}+cx+d$ is a polynomial of the 3rd degree, it is a cubic equation.

The equation $y=mx+c$ is a polynomial of the 1st degree, it is the equation of a sloping straight line.

The equation $y={{a}_{n}}{{x}^{n}}+{{a}_{(n-1)}}{{x}^{(n-1)}}+a(n-2)x(n-2)....+{{a}^{2}}{{x}^{2}}+ax+C$

is a polynomial of degree n. It is the general form of a polynomial equation.

Sub equations in a polynomial are called

a, b, c, and d are called coefficients, ${a}_{(n-1)}$ is the nth-1 coefficient of the general polynomial.

If we want to fit a polynomial to the canvas, say the quadratic equation, we must evaluate a, b, and the constant c.

Note zero is a value, if b=0 and d=0, we only have to evaluate a, which we did for the simple parabola and cubic.

The graph shows the terms for the equation $y=a{{x}^{2}}+bx+c$

The blue graph is for the term $y=a{{x}^{2}}$, the red graph is for the term $bx$

The constant c is the value of y when x=0, that is where the red line intercepts the y axis.

The green graph is for the quadratic equation $y=a{{x}^{2}}+bx+c$

It is useful to draw the terms individually to ensure the graph of $y=a{{x}^{2}}+bx+c$ can be made to fit the canvas.

In the animation the hexagon follows the motion path defined by $y=a{{x}^{2}}+bx+c$

We need to calculate the coefficients a

When x=0, y=a

x0, was set to

The maximum value of

y1max, the maximum y

a

${{y}_{2}}Max=0.2canvas.height/2$, ${{a}_{2}}={{y}_{2}}Max/Math.pow(xMax,2)$

$y3Max=0.6canvas.height/2$, ${{a}_{3}}={{y}_{3}}Max/Math.pow(xMax,3)$

The straight line (red) was plotted using ${{y}_{1}}={{a}_{1}}x+{{a}_{0}}$

The squared term (blue) was plotted using ${{y}_{2}}={{a}_{2}}{{x}^{2}}$

The cubed term (green) was plotted using ${{y}_{3}}={{a}_{3}}{{x}^{3}}$

The motion path (magenta) was plotted using $y={{a}_{3}}{{x}^{3}}+{{a}_{2}}{{x}^{2}}+{{a}_{1}}x+{{a}_{0}}$

The JavaScript equation for initialising the y value, x=0, star is:

$yInit=(a3*Math.pow(-xMax+x,3)+a2*Math.pow(-xMax+x,2)+a1*(-xMax+x)=a0)$

This is also the animation equation of the star as the value of x is incremented by 2, from $-xMax$ to $xMax$

The star is made to follow the motion path, rotate and morph so that the length of the star "spikes" increase.

The green quadratic curve represents a path that the black ball will travel along.

The blue quadratic curve, which is related to the green path, is the motion path of the ball.

The x and y coordinates of the blue path were offset by the radius of the black ball.

The ball is made to rotate as it travels

The yellow ball, which is off centre of the black, is used to give the perception of rotation.

The motion path, the blue path, is not drawn in the animation

When this animation was tested in Google Chrome and Firefox, it worked fine.

When it was tested in IE11,

The cause of this effect was a simple for loop used to draw the green path on every frame of the animation.

When the for loop was removed the ball travelled and rotated at the correct speed using IE11.

Of course the green path was not then shown.

The ball was made to travel at the correct speed in IE11 by using

The simple parabola is an example of an algebraic equation.

The equation for the simple parabola shown is: $y=a{{x}^{2}}$

$a$ is a constant that can have any value, including zero and one.

The size of the parabola on canvas is made to fit in an imaginary rectangle.

The rectangle width is defined as $xpMax-(-xpMax)=2xpMax$ , the height of the rectangle is $ypMax$

The parabola is made the fit the rectangle by using the equation $a=ypMax/Math.pow(xpMax,2)$

The parabola is drawn from left to right, starting at $-xpMax,ypMax$, passing through $0,0$ and finishing at $+xpMax,ypMax$

The javaScript code for drawing the parabola is 19 lines long.

The code for drawing the graph axes and adding text is 18 lines long.

Parabolas can be used in to define animation motion paths: the paths do not need to be drawn.