要绘制等距平面,请使用变换矩阵设置 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);
现在所有的渲染都在那个等距平面上。
您可以将轴设置为您希望的任何等距投影。我使用的那个会增加一个像素的面积。这一切都取决于 x 和 y 轴的长度和相对方向。
更新
只是出于兴趣。
由于许多等轴测投影倾向于改变每个像素的总面积,因此我包含了一个简单的计算,无论使用何种投影,都会对像素面积进行归一化。 (对于我给出的投影,它恰好是 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 = "https://i.stack.imgur.com/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);