我想将每个矩形表示为具有宽度和高度的二维矩形。 因此,例如,当您在编辑器中创建 map 时,您可以绘制二维矩形,并且该创建可以转换为等距平面。 等轴测平面的宽度是从北到东南(从菱形的顶部到右侧。) 高度是从北到西南。 (从上到左)
现在我有两个问题。
第一个问题
我正在 Canvas 上绘制这个等距 map ,我使用屏幕外 Canvas 单独绘制每个平面。我想计算屏幕外 Canvas 的二维宽度和高度。我用这个数学来做到这一点:
var canvasWidth = Math.cos(30) * planeWidth + Math.cos(30) * planeHeight;
var canvasHeight = Math.sin(30) * planeWidth + Math.cos(30) * planeHeight;
// still remember that planeWidth and planeHeight are isometric, so oblique sides
但这并没有给我正确的 Canvas 尺寸。 我想知道的另一件事是用像素计算斜边是否明智。
第二个问题 我想对飞机使用“纹理”图像。所以,我有这样的图像:
我的想法是存储每个图像的斜边,就像平面的宽度和高度一样。 当我想用特定图像绘制平面时,我可以重复该图像。
主要目标是创建具有像素精确的给定宽度和高度的等距平面。并且飞机应该有图像作为纹理。图像已经是等轴测的,因此可以像等轴测图 block 一样重复和剪切它们。
我的问题: 1. 我想知道使用斜边作为宽度和高度是否明智,无论如何找到一种继续使用二维尺寸的方法不是更好吗?
在屏幕外 Canvas 上创建一个 2d 矩形,并用非等距纹理图像填充它们,然后转换该 Canvas ,这不是更聪明吗?
如果我使用斜边来表示平面和图像的宽度/高度,那么该长度是真实长度吗?它就像一个线性函数:它只是像素。每2个水平,1个垂直。水平方向为奇数,垂直方向不会给出整数。 (我想这会给我以后带来不必要的麻烦)。
最佳答案
要绘制等 Angular 平面,请使用变换矩阵设置 x 轴和 y 轴。
假设x轴沿向量(1,0.5),y轴沿向量(-1,0.5),原点仍位于左上角。
如此定义。
var xAxis = {
x : 1,
y : 0.5,
}
var yAxis = {
x : -1,
y : 0.5,
}
var origin = {
x : 0,
y : 0,
}
要设置转换只需使用
ctx.setTransform(xAxis.x, xAxis.y, yAxis.x, yAxis.y, origin.x, origin.y);
现在所有渲染都在该等轴测平面上。
您可以将轴设置为您想要的等 Angular 投影。我使用的会增加像素的面积。这完全取决于 x 轴和 y 轴的长度和相对方向。
更新
纯粹是出于兴趣。
由于许多等 Angular 投影都有改变每个像素总面积的趋势,因此我包含了一个简单的计算,无论使用哪种投影,都会对像素面积进行标准化。 (对于我给出的投影,它恰好是 2 的平方根的 1)
使用xAxis
和yAxis
计算该投影的像素面积
var area = (xAxis.x * ( xAxis.y + yAxis.y ) + ( xAxis.x + yAxis.x ) * yAxis.y) - (xAxis.y * ( xAxis.x + yAxis.x ) + ( xAxis.y + yAxis.y ) * yAxis.x)
面积平方根除以所需的比例
var scaleBy = 1 / Math.sqrt(area);
您可以将其直接应用于轴,如下所示...
xAxis.x *= scaleBy;
xAxis.y *= scaleBy;
yAxis.x *= scaleBy;
yAxis.y *= scaleBy;
ctx.setTransform(xAxis.x, xAxis.y, yAxis.x, yAxis.y, origin.x, origin.y);
或者在设置变换后通过ctx.scale
应用它
ctx.setTransform(xAxis.x, xAxis.y, yAxis.x, yAxis.y, origin.x, origin.y);
ctx.scale(scaleBy, scaleBy);
示例
该演示展示了此方法的简单应用(没有像素归一化)。
var canvas = document.createElement("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.style.position = "absolute";
canvas.style.left = "0px";
canvas.style.top = "0px";
document.body.appendChild(canvas);
function demo(){
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var ctx = canvas.getContext("2d");
ctx.font = "80px arial black";
ctx.lineWidth = 8;
ctx.lineJoin = "round"
ctx.strokeStyle = "green";
ctx.fillStyle = "#aF6";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
// the axis and origin
var xAxis = {x : 1, y: 0.5};
var yAxis = {x : -1, y: 0.5};
var origin = {x : 0, y : 0};
// cludge factor dividing by two to fit the display area
ctx.setTransform(xAxis.x / 2, xAxis.y / 2, yAxis.x / 2, yAxis.y / 2, origin.x, origin.y);
// draw big text
ctx.strokeText("Isometric",ctx.canvas.width/2,0);
ctx.fillText("Isometric",ctx.canvas.width/2,0);
// half size text
ctx.font = "40px arial black";
ctx.lineWidth = "4";
ctx.strokeText("projection",ctx.canvas.width/2,60);
ctx.fillText("projection",ctx.canvas.width/2,60);
// tiny text
ctx.font = "16px arial black";
ctx.lineWidth = "3";
ctx.strokeText("using 2D context transformation",ctx.canvas.width/2,100);
ctx.fillText("using 2D context transformation",ctx.canvas.width/2,100);
// add an image to demonstrate that the project will be applied to
// anything that is rendered.
var image = new Image();
image.src = "/image/C7qq2.png?s=328&g=1";
image.addEventListener("load",function(){
ctx.drawImage(this,ctx.canvas.width-this.width,-this.height * 1.2);
});
}
demo();
window.addEventListener("resize",demo);
关于javascript - 如何用图像绘制等 Angular 平面?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36506073/