【问题标题】:HTML5 Canvas rotate troubleHTML5 Canvas 旋转问题
【发布时间】:2019-05-29 13:54:53
【问题描述】:

我有一个画布元素,我在其上绘制了许多图像并用文本覆盖它们。不幸的是,这个问题需要旋转其中一些图像和相应的文本。除此之外,还有一些图片必须有相应的背景颜色的问题(图片是平面图的桌子的简单轮廓)

这是我为处理向计划中添加单个办公桌而构建的功能。我遇到的问题是,当我使用旋转时,文本和背景颜色都不会出现,而如果我不旋转图像,则会正确显示,除了它们没有旋转并且背景 fillRect() 方向为 90 度关闭。

function redrawDesk(desk, ctx, color) {
    var rotate = desk.rotation == 90 || desk.rotation == 270;
    if (rotate) {
        ctx.save();
        ctx.rotate(Math.PI / 2);

        ctx.clearRect(desk.left, desk.top, desk.width, desk.height);
        ctx.restore()
    }

    var img = $("#desk_" + desk.rowID)[0];
    ctx.drawImage(img, desk.left, desk.top, desk.height, desk.width);

    var x = desk.left;
    var y = desk.top;
    var h = desk.height;
    var w = desk.width;

    if (rotate) {
        //ctx.save()
        ctx.rotate(Math.PI / 2);
        var tmp=x;
        x=y;
        y=tmp;
        tmp=h;
        h=w;
        w=tmp;
    }        
    ctx.textAlign = "center";

    ctx.fillText(desk.deskID, x + w / 2,y + h/ 2);
    if (color) {
        ctx.fillStyle = color;
        ctx.fillRect(x, y, w, h);
    }
    //ctx.restore();
    if (rotate) {

        ctx.rotate(Math.PI / -2);
    }
}

谢谢

【问题讨论】:

    标签: html5-canvas


    【解决方案1】:

    主要问题是您将桌面和文本定义为绝对坐标。

    在本地坐标系中定义对象。例如,桌子有高度和宽度,但没有位置。它相对于自身的绘制(大约 0,0)

    const desk = {
        w : 10, h : 10,
        color : "blue",
        draw() {
           ctx.fillStyle = this.color;
           ctx.fillRect(-this.w / 2, -this.h / 2, this.w, this.h);
        }
    };
    

    然后,您可以通过定义其中心的位置将桌子定位到世界坐标系(画布)中。

    function drawObj(obj, x, y) { // what to draw and where
        ctx.setTransform(1,0,0,1,x,y);  // Same as ctx.translate if 2D API is in default context
                                        // The means you do not have to use ctx.save and 
                                        // ctx.restore in this function
        obj.draw();  // draw desk
    }    
    

    对于一个完整的转换,它几乎相同

    function drawObj(obj, x, y, scale, rotate) { // rotate is in radians
        ctx.setTransform(scale, 0, 0, scale, x, y);  
        ctx.rotate(rotate);
        obj.draw();  
    }    
    

    要添加文本,您可以将其作为对象添加到桌面并将其绘制到自己的本地坐标系中

    desk.name = {
        text : "Desk",
        color : "black",
        font : "bold " + 20 + "px Calibri",
        draw() {  
            ctx.font = this.font;
            ctx.textAlign = "center";
            ctx.fillStyle = this.color;
            ctx.fillText(this.text, 0,0);
        }
    };
    

    您现在可以使用绘图对象功能绘制桌子和名称

    drawObj(desk,200, 200, 1, Math.PI / 2); // Draw at 200,200 rotated 90deg CW
    drawObj(desk.name, 200, 200, 1, Math.PI / 2); // draw the text rotated same and centered over desk
    
    // Or if the text should be above and not rotated
    drawObj(desk.name, 200, 200 - 30, 1, 0);
    

    由于上述函数使用setTransform,您可能需要恢复转换。有两种方法可以做到这一点。

    ctx.resetTransform(); // Check browser support for this call
    
    ctx.setTransform(1,0,0,1,0,0); // same as above just does it manaly
    

    【讨论】:

      【解决方案2】:

      在我的代码中,我测试了是否需要轮换。如果是这样,我在画布上设置了一个翻译来给我一个新的起点:ctx.translate(x, y);这使我能够简化用于放置文本和背景颜色的位置设置,这意味着它们可以正确显示。这是与原始代码进行比较的更改代码:

      if (rotate) {
          ctx.save();
          tmp = h;
          h = w;
          w = tmp;
          ctx.translate(x, y);
      }
      if (color) {
          ctx.fillStyle = color;
          ctx.fillRect(0, 0, w, h);
      }
      ctx.font = "bold " + w / 2 + "px Calibri";
      ctx.textAlign = "center";
      ctx.fillStyle = "#000";
      var c=ctx.canvas;
      ctx.rotate(Math.PI / -2);
      ctx.fillText(desk.deskID, 0-h/2, w/2); //x + w / 2, y + h / 2);
      ctx.restore();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-08-06
        • 2022-01-10
        • 2012-02-27
        • 2019-04-06
        • 1970-01-01
        • 2014-07-24
        • 2012-02-14
        • 1970-01-01
        相关资源
        最近更新 更多