我在画布上画了一个简单的3坐标图;
我定义了几个与
一起使用的常量var width = window.innerWidth * 0.5 , height = window.innerWidth * 0.5;
var cx = width / 2, cy = height / 2, cz = height / 2, blcx = 0, blcy = height, brcz = height, brcx = width, brcy = height;
var ySegment = height / 30;
var xSegment = width / 30;
var xSegmentRatio = xSegment / width;
var ySegmentRatio = ySegment / height;
cx和cy和cz都是指画布的中心。 blcx
表示左下角x,brcy
是右下角y等等。我意识到这有点黑客,因为这是第一次尝试这样做,但如果你忍受我,我有一个真正的概念,我想在这里抓住。
然后画出这样的红线:
(function() {
var gridCx = cx, gridCy = cy, gridCz = cz;
var gridBlCx = blcx, gridBlCy = brcy;
for (var i = cx; i < width; i++) {
gridCx += xSegment;
gridBlCx += ySegment;
gridCzx -= gridCzx * (xSegmentRatio / ySegmentRatio);
ctx.beginPath();
ctx.moveTo(gridCx, cy);
ctx.lineTo(gridBlCx, height);
ctx.strokeStyle="#FF0000";
ctx.stroke();
}
})();
我试过了:
gridCzx -= gridCzx * xSegmentRatio;
gridCzy += gridCzy * ySegmentRatio;
ctx.beginPath();
ctx.moveTo(gridCzx, gridCzy);
ctx.lineTo(width, gridCzy);
ctx.strokeStyle = "#ff0000";
ctx.stroke();
得到了这个:
但我意识到我缺少一些基本的数学概念。感谢您提供的任何见解! 我的基本问题是:如何选择距离中心一定距离的z轴上的点?
答案 0 :(得分:2)
Axis告诉我们如何移动
要在第一维x中找到一个点,请沿x轴从左向右移动。要在第二个维度y中找到一个点,您必须整合第一个和第二个维度,从而从左到右依次为第一个x,然后在屏幕下沿y轴进行第二个。
每个尺寸都依赖于前一个尺寸的定位。它也依赖于轴,x和y轴彼此成90度,但它们可以是45或120,找到一个点的2D坐标没有任何区别。首先沿X轴,然后沿y轴Y.
矢量函数
因为显示器只是2D,所以轴可以表示为2D矢量。矢量的长度表示轴的比例。因此,对于x轴,如果我将轴定义为2D(显示坐标)向量(2,0),那么我说它对于x坐标中的每个单位为2和0。如果我想要在x坐标10处,我将它乘以轴以获得屏幕位置。
因此对代码......
function screenCoord(x,y){ // creates a coordinate in screen space
// screen space is always in pixels
// screen space always has the origin (0,0) at the top left
return {
x : x,
y : y,
}
}
function screenVector(x,y){ // a vector in screen space it points in a direction
// and its is in pixels
return { // basically identical to the last function
x : x,
y : y,
}
}
所以让我们定义我有(2,0)按比例放大的X轴
var xAxis = screenVector(2,0);
现在x位置说10
var xPos = 10
要找到它的位置,我们需要沿x轴获取屏幕坐标。我们通过将xAxis乘以xPos来实现。为了更容易,我们可以创建一个向量乘法函数
function multiply(vector, value){
var x = vector.x * value; // multiply the vector x by value
var y = vector.y * value; // multiply the vector y by value
return screenCoord(x,y)
}
现在找到xPos的第一个维度位置
var screenPos = multiply(xAxis, xPos); // returns the screen position of x = 10
现在要做第二个维度,我们将其添加到上一个维度。让我们定义一个函数来将向量添加到另一个
function add(vector1, vector2){ // adds two vectors returning a new one
var x = vector1.x + vector2.x;
var y = vector1.y + vector2.y;
return screenCoord(x,y);
}
现在让我们创建y轴
var yAxis = new screenVector(0,2); // y goes down the screen and has no x change
和y pos
var posY = 10;
现在让我们从x
开始吧var screenPosX = multiply(xAxis,posX); // get the x position on the screen
var screenPosY = multiply(yAxis,posY); // get the y position on the screen
现在我们添加两个坐标的结果
var screenXY = add(screenPosX,screenPosY);
我们在x = 10和y = 10的屏幕上有一个坐标(在这种情况下,它在20英尺处的像素位置20处。
第三维
现在猜测第3个z维度会发生什么并不需要太多。对于沿x轴的x,沿y轴为y,然后沿z轴为z
因此定义z轴
var yAxis = new screenVector(1,-1); // z axis along the diagonal from bottom left to top right
现在是z coord
var posZ = 10;
所以要找到我们的3d位置,x沿其轴,然后沿其添加y,然后沿轴添加z
var screenPosX = multiply(xAxis,posX); // get the x position on the screen
var screenPosY = multiply(yAxis,posY); // get the y position on the screen
var screenPosZ = multiply(zAxis,posZ); // get the z position on the screen
需要将它们一起添加
var screenXY = add(screenPosX,screenPosY);
然后z
var screenXYZ = add(screenPosXY,screenPosZ);
并且您有如何从一组坐标转换到另一组坐标。它被称为变换
原点
我们遗漏了最后一点信息。起源。这是屏幕上的坐标0,0,0(x,y,z)。它是变换的最后一部分,位于屏幕坐标(x,y)
中var origin = screenCoords(100,500); // set the origin at 100 pixels across 500 down
从上次计算中我们得到了屏幕空间中的screenXYZ坐标,我们需要将原点添加到它
screenXYZ = add(screenXYZ ,origin);
现在你可以在2d屏幕上从原点绘制坐标(10,10,10)(x,y,z)处的像素。
矩阵
如果您了解自己刚刚学会了如何使用3D转换矩阵,那么希望有所帮助。它将x,y,z轴保持为三个2D方向的集合,以及原点的坐标。矩阵执行完全相同的功能步骤,只是它在一个简单的数组中使它更有效,并遵循一些矩阵规则允许非常复杂的变换。例如,如果要旋转,您需要做的就是更改轴的方向并旋转对象。要更改比例,只需更改轴的长度,移动对象只需更改原点的位置。
答案 1 :(得分:1)
事实证明,JavaScript的Math.cos()
和Math.sin()
在这种情况下非常有用。我不得不考虑它的方式就好像有连续的同心圆,半径从我的网格段长度开始,每次连续加倍。从那里,我谷歌一些关于如何在给定学位的圆上找到点。事实证明,圆形,如三角形,有度,即弧度,而我的z-index方向的圆是5PI / 4。因此,我的函数看起来像这样:
for (var i = 0; i < zDistance; i++) {
var r = xSegment * i;
ctx.beginPath();
ctx.arc(cx, cy, r, 0, 2 * Math.PI);
ctx.strokeStyle="white";
ctx.stroke();
var zRadian = {
divided: function() {
return 5 * Math.PI
},
divisor: function() {
return 4;
}
}
var zRadian = zRadian.divided() / zRadian.divisor();
var x = cx + r * Math.cos(zRadian);
var y = cy - r * Math.sin(zRadian);
ctx.beginPath();
ctx.fillText('(' + x + ', ' + y + ')', x, y);
ctx.stroke();
}
结果如下: