Prev: W1, Next: W3, Quiz of the week: Q2
Links: Zoom, TopHat (223815), Calculator:
Slide:

# Animation and Redraw

📗 Most computer displays are flicker-based: Wikipedia.
📗 The HTML Canvas is erased and redrawn frame by frame.
📗 Drawing could be too slow or too fast.
📗 Double buffering is used: two images (pixel arrays), one used for drawing in the background, one used for display, are swapped so the display only shows finished images and this also helps with frame rate constancy.

Example
Frame Image 1 Image 2
1 Draw Show
2 Show Draw
3 Draw Show
4 Show Draw
... ... ...




# Canvas Buffering

📗 The web browser handles double buffering: JavaScript cannot control this process.
📗 window.requestAnimationFrame waits until after a buffer swap: Doc.
📗 Animation is drawing a different image for every frame.
📗 With HTML Canvas, animation is a drawing function of time, so a typical animation function looks like:
let draw = function(t) {
   \\ draw frame at time t, measured in milliseconds;
   window.requestAnimationFrame(draw);
}
window.requestAnimationFrame(draw);

# Bouncing Box [TopHat]

📗 Why does the box bounce with the formula \(450 - 250 \left| \sin\left(t\right) \right|\)?
📗 How to make the box bounce faster?
📗 How to make the box move horizontally too?
Demo bounce
📗 Note: sin(t) is a simple mathematical trick to make sure the position of the box is bounded by -1 and 1 (and abs(sin(t)) bounds it by 0 and 1), the correct trajectory of a falling or bouncing object is better approximated by a quadratic function: Wikipedia. Try this in Workbook 2: Galleries.

# Moving Things in Circles [TopHat]

📗 Why does the box move in a circle with the formula \(\begin{bmatrix} 250 + 200 \sin\left(t\right) \\ 250 + 200 \cos\left(t\right) \end{bmatrix}\)?
📗 How to make the box move faster?
📗 How to make the box move in an "8"-shaped path instead?
Demo animate_time



# Display List

📗 Making a sequence of images, each image as a mathematical function of time can be difficult.
📗 Alternatively, a display list (a list of objects, or primitives), including their position, velocity, acceleration etc can be stored and updated every time requestAnimationFrame is called:
let objects = [];
let draw = function() {
   \\ update objects and draw objects
   window.requestAnimationFrame(draw);
}
window.requestAnimationFrame(draw);

# Moving Things in Circles Again [TopHat]

📗 Why does the box move in a circle with the update \(\begin{bmatrix} x \\ y \end{bmatrix} \to  \begin{bmatrix} x + \dfrac{y - 250}{100} \\ y - \dfrac{x - 250}{100} \end{bmatrix}\)?
Math Notes The velocity is the derivative of position as a function of time:
\(\dfrac{d}{dt} \begin{bmatrix} x \\ y \end{bmatrix}\) = \(\dfrac{d}{dt} \begin{bmatrix} 250 + 200 \sin\left(t\right) \\ 250 + 200 \cos\left(t\right) \end{bmatrix}\)
= \(\begin{bmatrix} 200 \cos\left(t\right) \\ -200 \sin\left(t\right) \end{bmatrix}\)
= \(\begin{bmatrix} 200 \dfrac{y - 250}{200} \\ -200 \dfrac{x - 250}{200} \end{bmatrix}\)
= \(\begin{bmatrix} y - 250 \\ - \left(x - 250\right) \end{bmatrix}\)
= \(c \begin{bmatrix} \dfrac{y - 250}{100} \\ \dfrac{-\left(x - 250\right)}{100} \end{bmatrix}\), c = 100.
📗 Is the box really moving in a circle? How to make it better?
Demo animate_position
📗 Note: for Workbook 2, the projectile motion can be approximated this way: Galleries, but in general, approximating the velocity by derivatives when moving objectives along a curve is not good due to accumulated discretization errors.



# Event Driven Animation

📗 Animation can be driven by events, and in this case, the sequence of images can be functions of the event parameters, for example, mouse position or slider value.
📗 The HTML Canvas (not its context) receives events, for example, MouseEvent Doc, TouchEvent Doc, KeyboardEvent Doc.
📗 Typically, a drawing function is defined for each event, for example,
canvas.onmousemove = function(event) {
  \\ draw objects based on the mouse move event
}
canvas.onclick = function() {
  \\ draw objects if a click event is received
}

# Mouse Events

📗 It is easier to work with mouse position in the HTML Canvas coordinate, but a mouse event returns the mouse position in the window coordinate system; wherefore, the following conversion is usually done.
let box = event.target.getBoundingClientRect();
let x = event.clientX - box.left;
let y = event.cleintY - box.top;
📗 event.ctrlKey, event.shiftKey, event.altKey checks if the "Ctrl", "Shift", or "Alt" keys are pressed during the mouse event.

# Move Things by Mouse [TopHat]

📗 Currently, the mouse is creating small rectangles: change the code so that creates lines instead.
Demo animate_event
📗 Note: in the demo, the "onmouseenter" function does the context.beginPath() and context.moveTo(...mouse).



# Moving Things in Circles Again, Again [TopHat, Updated]

📗 Now draw a rectangle and make it move in a circle facing the direction of the movement.
📗 Coming up with the formula to compute the vertices of the rectangle is complicated (fillRect function cannot rotate the rectangle).
📗 Trick: always draw the same rectangle then translate, rotate, and scale.
Demo animate_transform
Math Notes The rotation angle is arctan of the change in y position \(250 + 200 \cos\left(t\right)\) over the change in x position \(250 + 200 \sin\left(t\right)\):
\(arctan\left(\dfrac{dy}{dx}\right)\) = \(arctan\left(\dfrac{\dfrac{dy}{dt}}{\dfrac{dx}{dt}}\right)\)
= \(arctan\left(\dfrac{-\left(200 \sin\left(t\right)\right)}{200 \cos\left(t\right)}\right)\)
= \(-arctan\left(\dfrac{\sin\left(t\right)}{\cos\left(t\right)}\right)\)
= \(-arctan\left(\tan\left(t\right)\right)\)
= \(-t\).
That is the reason why there should be a negative sign.

# Context Transformation

📗 Unfortunately, HTML Canvas does not have functions to translate, rotate, and scale primitives and groups of primitives; it does have functions to translate, rotate, and scale the context.
📗 Using the HTML Canvas pen analogy: instead of translating, rotating, and scaling the primitives: first translate, rotate, and scale the paper, then draw the primitives.
📗 Professor Gleicher's demo: Link.

# Order of Transformation

📗 The usual order to place a single object centered at origin is TRS:
➭ When writing code: context.translate(x, y); context.rotate(r); context.scale(sx, sy);.
➭ When reading in reverse: scale, rotate, translate.
Demo transform_list

# Move the Cat [TopHat]

📗 Move the cat to the center and make it larger, by scaling then translating and by translating then scaling.
📗 Order matters!
Demo transform_order



# Scaling around Center

📗 To scale around (x, y):
context.translate(x, y);
context.scale(sx, sy);
context.translate(-x, -y);
draw();
📗 Read this in reverse:
➭ Draw,
➭ Move the center to origin,
➭ Scale at the origin (so the origin does not move),
➭ Move the center back.
📗 Negative scaling is reflection in x-axis or y-axis.

# Rotation around Center

📗 To rotate around (x, y):
context.translate(x, y);
context.rotate(r);
context.translate(-x, -y);
draw();
📗 Read this in reverse:
➭ Draw,
➭ Move the center to origin,
➭ Rotate around the origin (so the origin does not move),
➭ Move the center back.

# Rigid Transformation

📗 A transformation is a rigid transformation if:
➭ Distances between points are preserved.
➭ Handedness is preserved: preserves rotation from x-axis to y-axis (HTML Canvas is left-handed, math graph coordinate system is right-handed).
📗 Two transformations that are rigid:
➭ Translation.
➭ Rotation.
➭ Scaling does not preserve distance.
➭ Mirror reflection (negative scaling) does not preserve handedness.

# Moving Things in Circles, the Last Time [TopHat]

📗 The rectangle can move around a circle by rotating it around the center of the Canvas.
📗 Unfortunately, this trick only works for moving things in a circle (or ellipse with scaling).
Demo animate_time

# Combine Transformation and Event Animation

📗 Write the transformation of the Cat as a function of the slider value.
📗 Slider controls "time".
📗 Checkbox controls slider.
Demo animate_slider

# Add a Bee to Fly around the Cat [TopHat]

📗 Add a Bee to the scene. Make the Cat run around a circle and the Bee fly around the Cat. To get the emojis: Link.
Demo animate_slider

# Local Coordinate System

📗 A common good practice to draw an object consisting of multiple parts (primitives or other objects) is:
➭ Draw at a meaningful zero (origin).
➭ Parent object places it in the appropriate location (position, rotation and scale).



# Articulated Object [TopHat]

📗 Write the robotic arm movement as a function of the sliders (v1, v2, v3).
📗 Change the code so that middle piece is shorter and all pieces would fit on the screen.
📗 Change the code so that middle piece can only rotate 180 degrees.
Demo arm

# Articulated Motion [TopHat]

📗 Make the stick figure dance (as a function of the slider value):
Demo figure

# Lecture Summary

📗 Canvas frame buffering.
📗 Animation as image sequence as a function of time.
📗 Animation using display lists.
📗 Animation driven by events.
📗 Transformations: translate, rotate, scale.
📗 Rigid transformations.
📗 Order and composition of transformation.


📗 Notes and code adapted from the course taught by Professor Michael Gleicher.
📗 Please use Ctrl+F5 or Shift+F5 or Shift+Command+R or Incognito mode or Private Browsing to refresh the cached JavaScript: Code.
📗 You can print the notes: .
📗 Anonymous feedback can be submitted to: Form.

Prev: W1, Next: W3, Quiz of the week: Q2





Last Updated: May 07, 2024 at 12:22 AM