[根据 OP 的进一步澄清进行编辑]
好的,我现在对你的问题有了更好的理解。你想让你的相机镜头透视你世界中的物体。
如果您的相机仅在与您的世界对象相关的 X 方向上看,您可以简单地使用视差。为此,您可以在画布上应用 2 个图层,这些图层在 X 方向上以不同的速度滚动。这是全景视差。因此,对于每一帧,像这样的伪代码绘制 2 层:
// Move the back layer
backLayerX += 3;
ctx.save();
ctx.translate(backLayerX,backLayerY);
// draw the objects in your back layer now
ctx.translate(-backLayerX,-backLayerY);
ctx.restore();
// Move the front layer faster than the back layer
frontLayerX += 10;
ctx.save();
ctx.translate(frontLayerX,frontLayerY);
// draw the objects in your front layer now
ctx.translate(frontLayerX,frontLayerY);
ctx.restore();
如果您在 X 方向上移动相机本身,您还必须更改前后图层的平移速度。
如果您的相机也相对于您的世界对象在 Z 方向(相机更近)查看,则该过程要复杂得多 。
例如,如果您靠近一座雕像,雕像会显得更大——ctx.scale(2,2)。背景景物也变大了,但没那么快——ctx.scale(1.25,1.25)。
然后如果你也向左走一步,那么雕像的左侧比雕像的右侧略大——上下文倾斜。背景也偏斜,但非常非常轻微。
然后,如果你也站在椅子上(改变 Y 方向),你会得到另一种倾斜。
即使有雕像,您的相机也永远无法移动,因为您的雕像是 2D 的——只是雕像的纸板切口。从摄像机的角度来看,雕像实际上会消失!
我希望我已经让您开始了您的项目,但完整的答案是 waaaaaaaaaay 超出了 Stackoverflow 的答案——这是一门关于计算机图形学的大学课程。
我确实有一个在线教程推荐给你。Wolfgang Hurst有一个关于 Perspective 的精彩讲座。这是他的 13 部分在线大学课程中的第 7 讲。您可以通过两种方式查看他的讲座。广泛地查看以了解赋予相机视角所涉及的概念。或深入查看并获得数学算法: http ://www.youtube.com/watch?v=q_HA-x5AujI&list=PLDFA8FCF0017504DE
祝你好运和学习...... :)
[以下内容解决了 OP 的原始问题]
这是有关如何在画布中成功旋转任何内容的快速教程
整个世界围绕一个 X/Y“注册点”旋转。
您可以通过在 ctx.rotate(angle) 之前执行 ctx.translate(X,Y) 来设置注册点。
在这个旋转空间中绘制“世界”对象后,您必须通过执行 translate(-X,-Y)重新设置注册点。
所以世界旋转是这样的:
- 上下文.save();
- Context.translate(registrationX, registrationY);
- 上下文.旋转(角度);
- 画东西。
- Context.translate(-registrationX, -registrationY);
- 上下文.restore();
这是理解旋转和注册点的好方法:
- 拿一张纸,在纸上画一个字母。
- 拿一支铅笔并在页面上的任何位置按住它。
- --铅笔点是注册点。
- --铅笔点是平移(X,Y)。
- 围绕铅笔尖旋转纸张。
- --纸张的旋转为rotate(angle)
- ——注意字母是如何随着纸张移动而旋转的。
- --您的红框将像字母一样旋转(围绕您的相机注册点)
- 将纸张重置为垂直旋转。
- --这个“不旋转”就像翻译(-X,-Y)
- 将铅笔移动到纸上的另一个点
- --再一次,这就像 translate(newX,newY)
- 再次旋转纸张,注意字母如何以不同的方式旋转。
这是代码和小提琴:http: //jsfiddle.net/m1erickson/nj29x/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; padding:30px; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var camX=100;
var camY=100;
var camRadius=40;
var camDegrees=0;
draw();
function draw(){
ctx.clearRect(0,0,canvas.width,canvas.height);
drawWorldRect(75,75,30,20,0,"blue","A");
drawWorldRect(100,100,30,20,15,"red","B");
drawCamera();
}
function drawWorldRect(x,y,width,height,angleDegrees,fillstyle,letter){
var cx=x+width/2;
var cy=y+height/2;
ctx.save();
ctx.translate(cx, cy);
ctx.rotate( (Math.PI / 180) * angleDegrees);
ctx.fillStyle = fillstyle;
ctx.fillRect(-width/2, -height/2, width, height);
ctx.fillStyle="white";
ctx.font = '18px Verdana';
ctx.fillText(letter, -6, 7);
ctx.restore();
}
function drawCamera(){
ctx.save();
ctx.lineWidth = 3;
ctx.beginPath();
// draw camera cross-hairs
ctx.strokeStyle = "#dddddd";
ctx.moveTo(camX,camY-camRadius);
ctx.lineTo(camX,camY+camRadius);
ctx.moveTo(camX-camRadius,camY);
ctx.lineTo(camX+camRadius,camY);
ctx.arc(camX, camY, camRadius, 0 , 2 * Math.PI, false);
ctx.stroke();
// draw camera site
ctx.fillStyle = "#222222";
ctx.beginPath();
ctx.arc(camX, camY-camRadius, 3, 0 , 2 * Math.PI, false);
ctx.fill()
ctx.restore();
}
function rotate(){
ctx.save();
ctx.translate(camX,camY);
ctx.rotate(Math.PI/180*camDegrees);
ctx.translate(-camX,-camY);
draw();
ctx.restore();
}
$("#rotateCW").click(function(){ camDegrees+=30; rotate(); });
$("#rotateCCW").click(function(){ camDegrees-=30; rotate(); });
$("#camUp").click(function(){ camY-=20; draw(); });
$("#camDown").click(function(){ camY+=20; draw(); });
$("#camLeft").click(function(){ camX-=20; draw(); });
$("#camRight").click(function(){ camX+=20; draw(); });
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=400 height=300></canvas><br/>
<button id="camLeft">Camera Left</button>
<button id="camRight">Camera Right</button>
<button id="camUp">Camera Up.</button>
<button id="camDown">Camera Down</button><br/>
<button id="rotateCW">Rotate Clockwise</button>
<button id="rotateCCW">Rotate CounterClockwise</button>
</body>
</html>