📗 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.
📗 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.
📗 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);
📗 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?
📗 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.
📗 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, MouseEventDoc, TouchEventDoc, KeyboardEventDoc.
📗 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
}
📗 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.
📗 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.
📗 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.