javascript - 如何用图像绘制等 Angular 平面?

标签 javascript html math canvas isometric

我想创建一个等轴测图。该 map 存在等距矩形,如图所示:isometric planes / (or 'rectangles')

我想将每个矩形表示为具有宽度和高度的二维矩形。 因此,例如,当您在编辑器中创建 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 尺寸。 我想知道的另一件事是用像素计算斜边是否明智。

第二个问题 我想对飞机使用“纹理”图像。所以,我有这样的图像: Tile images

我的想法是存储每个图像的斜边,就像平面的宽度和高度一样。 当我想用特定图像绘制平面时,我可以重复该图像。

主要目标是创建具有像素精确的给定宽度和高度的等距平面。并且飞机应该有图像作为纹理。图像已经是等轴测的,因此可以像等轴测图 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)

    使用xAxisyAxis计算该投影的像素面积

    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/

    相关文章:

    math - 确定两个 IP 地址是否在同一子网上 - 是否从 IP 地址中删除前导或尾随 0?

    algorithm - 检查两条线是否完全平行?

    javascript - 水平 iScroll 不起作用

    php - 在多个数据库中插入数据

    html - SVG - 剪辑路径仅在相同的 <svg> 标签中定义时才有效

    algorithm - 老师的算法

    javascript - 如何取消静音(并关闭自动播放)二十七岁的 YouTube 视频?

    javascript - 如何在文件对话框中选择文件或文件夹

    javascript - 使用 Javascript 验证优惠券代码

    html - 通过设备摄像头录制视频和音频