Javascript HTML5透视网格
我试图在画布上制作透视网格,我从另一个网站更改了功能,结果如下:Javascript HTML5透视网格,javascript,html,math,canvas,Javascript,Html,Math,Canvas,我试图在画布上制作透视网格,我从另一个网站更改了功能,结果如下: function keystoneAndDisplayImage(ctx, img, x, y, pixelHeight, scalingFactor) { var h = img.height, w = img.width, numSlices = Math.abs(pixelHeight), sliceHeight = h / numS
function keystoneAndDisplayImage(ctx, img, x, y, pixelHeight, scalingFactor) {
var h = img.height,
w = img.width,
numSlices = Math.abs(pixelHeight),
sliceHeight = h / numSlices,
polarity = (pixelHeight > 0) ? 1 : -1,
heightScale = Math.abs(pixelHeight) / h,
widthScale = (1 - scalingFactor) / numSlices;
for(var n = 0; n < numSlices; n++) {
var sy = sliceHeight * n,
sx = 0,
sHeight = sliceHeight,
sWidth = w;
var dy = y + (sliceHeight * n * heightScale * polarity),
dx = x + ((w * widthScale * n) / 2),
dHeight = sliceHeight * heightScale,
dWidth = w * (1 - (widthScale * n));
ctx.drawImage(img, sx, sy, sWidth, sHeight,
dx, dy, dWidth, dHeight);
}
}
功能密钥和显示图像(ctx、img、x、y、像素高度、缩放因子){
var h=最小高度,
w=最小宽度,
numSlices=Math.abs(像素高度),
切片高度=h/numSlices,
极性=(像素高度>0)?1:-1,
高度比例=数学绝对值(像素高度)/h,
宽度比例=(1-比例因子)/numslice;
对于(var n=0;n
它创建了几乎很好的透视栅格,但它没有缩放高度,因此每个正方形都具有相同的高度。它应该是什么样子,就在画布下面。我想不出任何数学公式能使高度与“透视距离”(顶部)成比例地扭曲。
我希望你能理解。对不起,语言错误 任何帮助都将不胜感激关于遗憾的是,除了使用3D方法外,没有合适的方法。但幸运的是,事情并没有那么复杂 下面将生成一个可由X轴旋转的网格(如图所示),因此我们只需聚焦该轴 为了理解发生了什么:我们在笛卡尔坐标空间中定义网格。用一个花哨的词来形容我们将点定义为向量而不是绝对坐标。也就是说,一个网格单元可以从0,0变为1,1,而不是例如10,20变为45,45,只是为了取一些数字 在投影阶段,我们将这些笛卡尔坐标投影到屏幕坐标中 结果如下: 好的,让我们深入探讨一下-首先我们设置一些投影所需的变量,等等:
fov = 512, /// Field of view kind of the lense, smaller values = spheric
viewDist = 22, /// view distance, higher values = further away
w = ez.width / 2, /// center of screen
h = ez.height / 2,
angle = -27, /// grid angle
i, p1, p2, /// counter and two points (corners)
grid = 10; /// grid size in Cartesian
为了调整网格,我们不调整循环(见下文),而是改变fov
和viewDist
以及修改网格
以增加或减少单元格数量
假设您想要更极端的视图-通过将fov
设置为128和viewDist
设置为5,您将使用相同的网格和角度获得此结果:
完成所有数学运算的“神奇”函数如下所示:
function rotateX(x, y) {
var rd, ca, sa, ry, rz, f;
rd = angle * Math.PI / 180; /// convert angle into radians
ca = Math.cos(rd);
sa = Math.sin(rd);
ry = y * ca; /// convert y value as we are rotating
rz = y * sa; /// only around x. Z will also change
/// Project the new coords into screen coords
f = fov / (viewDist + rz);
x = x * f + w;
y = ry * f + h;
return [x, y];
}
就这样。值得一提的是,正是新的Y和Z组合使得顶部的线条更小(在这个角度)
现在我们可以像这样在笛卡尔空间中创建网格,并将这些点直接旋转到屏幕坐标空间中:
/// create vertical lines
for(i = -grid; i <= grid; i++) {
p1 = rotateX(i, -grid);
p2 = rotateX(i, grid);
ez.strokeLine(p1[0], p1[1], p2[0], p2[1]); //from easyCanvasJS, see demo
}
/// create horizontal lines
for(i = -grid; i <= grid; i++) {
p1 = rotateX(-grid, i);
p2 = rotateX(grid, i);
ez.strokeLine(p1[0], p1[1], p2[0], p2[1]);
}
这有助于了解情况。如果需要透视正确的网格,则需要大量3D数学运算。最重要的构造是。如果您不想构建自己的3D引擎,可以使用现有的引擎,如。看看例子中的源代码,我想在画布中看到的唯一3D东西就是网格。没有严肃的3D数学,有没有办法做到这一点?我只需要添加一些改变每行水平线之间距离的东西(类似的东西)。有什么想法吗?我什么也没发现。使用图像作为背景有什么不对?我正在学习,我想知道如何做全透视网格之类的事情。EasyCanvas非常强大,我看到了文档。还有一个问题:脚本是通过在两侧添加单元格来创建网格的,这就是为什么它在网格中间旋转X。有没有办法以同样的方式旋转,但不是中间旋转,而是以最后一条水平线旋转?“我现在正努力做到这一点。”威兴当然。只需向上“平移”网格,即将单元格从-20添加到0,则0将是轴点,或旋转的基础。如果要在旋转后移动整个网格,只需在rotateX()生成的Y值中添加一个值即可。@Ken AbdiasSoftware是的,我已经自己翻译过了。再次感谢,祝你有一个美好的一天!
c1 = rotateX(cx, cy); /// upper left corner
c2 = rotateX(cx + 1, cy); /// upper right corner
c3 = rotateX(cx + 1, cy + 1); /// bottom right corner
c4 = rotateX(cx, cy + 1); /// bottom left corner
/// draw a polygon between the points
ctx.beginPath();
ctx.moveTo(c1[0], c1[1]);
ctx.lineTo(c2[0], c2[1]);
ctx.lineTo(c3[0], c3[1]);
ctx.lineTo(c4[0], c4[1]);
ctx.closePath();
/// fill the polygon
ctx.fillStyle = 'rgb(200,0,0)';
ctx.fill();