为假三维动画添加透视
Adding perspective to fake 3D animation
我正在制作一个基于画布的动画,并试图在2D画布中获得3D效果。
到目前为止,一切进展顺利!我的"三角形轨道线"运行得很好:
var c = document.createElement('canvas');
c.width = c.height = 100;
document.body.appendChild(c);
var ctx = c.getContext("2d");
function Triangles() {
this.rotation = {
x: Math.random()*Math.PI*2,
y: Math.random()*Math.PI*2,
z: Math.random()*Math.PI*2
};
/* Uncomment this for testing perspective...
this.rotation = {
x: Math.PI/2,
y: 0,
z: 0
};
*/
}
Triangles.prototype.draw = function(t) {
this.rotation.z += t/1000;
var i, points;
for( i=0; i<15; i++) {
points = [
this.computeRotation(Math.cos(0.25*i),-Math.sin(0.25*i),0),
this.computeRotation(Math.cos(0.25*(i+1)),-Math.sin(0.25*(i+1)),-0.1),
this.computeRotation(Math.cos(0.25*(i+1)),-Math.sin(0.25*(i+1)),0.1)
];
ctx.fillStyle = "black";
ctx.beginPath();
ctx.moveTo(50+40*points[0][0],50+40*points[0][1]);
ctx.lineTo(50+40*points[1][0],50+40*points[1][1]);
ctx.lineTo(50+40*points[2][0],50+40*points[2][1]);
ctx.closePath();
ctx.fill();
}
};
Triangles.prototype.computeRotation = function(x,y,z) {
var rz, ry, rx;
rz = [
Math.cos(this.rotation.z) * x - Math.sin(this.rotation.z) * y,
Math.sin(this.rotation.z) * x + Math.cos(this.rotation.z) * y,
z
];
ry = [
Math.cos(this.rotation.y) * rz[0] + Math.sin(this.rotation.y) * rz[2],
rz[1],
-Math.sin(this.rotation.y) * rz[0] + Math.cos(this.rotation.y) * rz[2]
];
rx = [
ry[0],
Math.cos(this.rotation.x) * ry[1] - Math.sin(this.rotation.x) * ry[2],
Math.sin(this.rotation.x) * ry[1] + Math.cos(this.rotation.x) * ry[2]
];
return rx;
};
var tri = new Triangles();
requestAnimationFrame(function(start) {
function step(t) {
var delta = t-start;
ctx.clearRect(0,0,100,100)
tri.draw(delta);
start = t;
requestAnimationFrame(step);
}
step(start);
});
正如你所看到的,它使用旋转矩阵来计算点旋转后的位置,我使用它来使用输出的x和y坐标绘制三角形。
我想通过使用z坐标并在动画中添加透视图来进一步提高这一点,这将使三角形在前景中稍微大一点,在背景中稍微小一点。然而,我不知道该怎么做。
我想这更像是一道数学题,而不是一道编程题,对不起!
定义焦距以控制透视量。值越大,透视的数量就越少。然后
var fl = 200; // focal length;
var px = 100; // point in 3D space
var py = 200;
var pz = 500;
然后获取屏幕X,Y
var sx = (px * fl) / pz;
var sy = (py * fl) / pz;
生成的点相对于面纱的中心,因此需要将其居中到画布。
sx += canvas.width/2;
sy += canvas.height/2;
这是一点。
它假设被观察的点在视图的前面,并且距离焦点的焦距更远。
我已经设法找到了一个基本的解决方案,但我相信还有更好的解决方案。因此,如果您有更完整的答案,请随时添加!但现在。。。
由于坐标系已经基于原点,视点直接在Z
轴上观察(x,y)
平面,因此实际上只需将(x,y)
坐标乘以与z
成比例的值就足够了。例如,x * (z+2)/2
在这种情况下做得很好
不过,肯定会有一个更合适、更通用的解决方案!
相关文章:
- 正在添加'X'按钮,在文本字段旁边使用javascript
- 如何在映射数组中添加换行符
- 正在将数据主题添加到所有项目
- ZeroClipboard-在复制之前添加到值
- 我可以在json对象中添加一个函数吗
- 将输入字段中的文本提交到我的数据库,同时将其添加到我的列表中
- 正在SharePoint 2013母版页中添加JQuery移动文件
- 如何添加浮动和非浮动,其他
- 添加文字和评论功能更新Div
- 如果使用 lodash 将属性存在于另一个对象中,则向对象添加属性
- 动态地改变“”的URL;添加新项目”;链接使用javascript/jquery
- 在函数中添加数组元素的数值
- 如何将歌曲添加到jPlayer
- 在html Select中添加搜索
- Java脚本时间添加
- FabricJs-限制主对象内添加对象的移动区域
- 如何在没有 css3 和 webGL 的情况下将 3D 透视添加到 html5 画布
- 动态向下面的透视柱形图添加注释 - 谷歌 API
- 为假三维动画添加透视
- WinJS:是否可以通过程序向数据透视项添加预算