HTML5 Canvas旋转麻烦

时间:2019-01-02 23:19:13

标签: html5-canvas

我有一个canvas元素,在上面可以绘制许多图像并将其与文本重叠。不幸的是,问题要求这些图像和相应的文本中的一些被旋转。除此之外,某些图像上必须具有相应的背景色(图像是平面图的办公桌的简单轮廓)

这是我构建的用于将单个办公桌添加到计划中的功能。我遇到的问题是,当我使用旋转时,文本和背景色都不会显示,而如果我不旋转图像,则正确显示,除非它们没有旋转并且背景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);
    }
}

谢谢

2 个答案:

答案 0 :(得分:0)

在我的代码中,我测试了是否需要轮换。如果是这样,我在画布上设置了一个笔译以给我一个新的起点: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();

答案 1 :(得分:0)

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

在局部坐标系中定义对象。例如,桌子有高度和宽度,但没有位置。它相对于自身的绘制(约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