HTML and CSS Reference
In-Depth Information
Calculate
scale
using the perspective formula we just covered, and size and position the ball accordingly.
The x and y positions of the ball on the canvas element are calculated from the vanishing point, adding on
the
xpos
and
ypos
times the
scale
. Thus, as scale becomes small, the ball converges on the vanishing
point.
When this example is run in your browser, at first it looks like you're simply dragging the ball with the
mouse. This is because
zpos
is zero, making
scale
1.0. So, no noticeable perspective is applied. As you
press the up cursor key, the ball appears to slide into the distance, as shown in Figure 15-4. Now as you
move the mouse around, the ball moves with it, but much less, giving you a parallax effect. If you want to
set up a scene to use parallax, hard-code the z value for each layer, rather than calculating it dynamically.
Figure 15-4.
Perspective in action
You might notice that if you keep pressing the down key, the ball gets very large. This is expected—if you
hold a pebble close to your eye, it looks like a boulder. However, if you continue to press the down key,
you see that the ball grows to an infinite size and then shrinks down again. (It's actually upside down and
reversed, but it's difficult to tell that from a circle.) This is the ball going
behind
the viewpoint.
Mathematically, what happens is that when
zpos
is equal to
-fl
, the formula
scale = fl / (fl +
zpos)
becomes
scale = fl / 0
. In many languages, dividing by zero gives you an error. In JavaScript,
it gives you
Infinity
. As you decrease
zpos
even more, you divide
fl
by a negative number.
scale
becomes negative, which when applied to the canvas context, has the effect of flipping the image
coordinate system, so your ball looks upside down and backward.
A simple way to handle this is to make the ball invisible if it goes past a certain point. If
zpos
is less than or
equal to
-fl
, you have a problem, so you can test for that condition and handle it. Here's the updated
drawFrame
function in document
02-perspective-2.html
(the rest of the script is the same as the
previous example):
(function drawFrame () {
window.requestAnimationFrame(drawFrame, canvas);
context.clearRect(0, 0, canvas.width, canvas.height);
if (zpos > -fl) {
var scale = fl / (fl + zpos);
xpos = mouse.x - vpX;
ypos = mouse.y - vpY;
ball.scaleX = ball.scaleY = scale;
ball.x = vpX + xpos * scale;
ball.y = vpY + ypos * scale;
ball.visible = true;