繁体   English   中英

HTML5 Canvas 旋转 function

[英]HTML5 Canvas rotate function

function drawNumbers(){
    var rad, num;

    cx.font= "30px Arial";
    cx.textAlign = "center";
    cx.textBaseline = "middle";

    //numbers around the inner circumference
     for(num=1; num < 13; num++){
    rad = num * Math.PI/6; //angle for every number
     cx.rotate(rad);
     cx.translate(0, -175);
     cx.rotate(-rad);
     cx.fillText(num.toString(),0,0);
     cx.rotate(rad);
     cx.translate(0, 175);
     cx.rotate(-rad);
    }
}

function drawHands(){
    //getting the time
    var time = new Date();
    var hours = time.getHours();
    var minutes = time.getMinutes();
    var seconds = time.getSeconds();

    //setting the radians based on the time
    //hour hand
    hours %= 12;
    hours = (hours * Math.PI/6) + (minutes * Math.PI/360) + (seconds * Math.PI/21600);
    hands(hours, radius * 0.04, radius * 0.5);

    //minute hand
    minutes = (minutes * Math.PI/30) + (seconds * Math.PI/1800);
    hands(minutes, radius * 0.03, radius * 0.65);

    //second hand
    seconds = (seconds * Math.PI/30);
    hands(seconds, radius * 0.01, radius * 0.68);
}

function hands(ang, width, length){
    cx.beginPath();
    cx.lineWidth = width;
    cx.lineJoin = "round";
    cx.lineCap = "round";
    cx.moveTo(0, 0);
    cx.rotate(ang);
    cx.lineTo(0, -length);
    cx.stroke();
    cx.rotate(-ang);
}

我在 W3Schools 中学习 HTML5 canvas,教程正在教如何制作工作时钟。 1. 我只是不明白额外的旋转在函数中是如何工作的。 2. 应用旋转 function 时,是否总是从 canvas 的原点 (0, 0) 中心旋转?

当您调用rotate function 时,它会旋转整个 canvas,想象拿着一幅画然后倾斜它。 它总是发生在原点附近。 绕不同点旋转的方法是先translate整个canvas,然后再rotate

回到绘画的类比,如果我们旋转了我们的绘画,一旦我们画好了我们的线条,我们就需要将绘画恢复到直立状态。 因此我们rotate(-ang) 如果我们进行了翻译,我们也必须以类似的方式撤销我们的翻译。

旋转以及我们为何撤消旋转

在下面的代码中,您可以看到我正在绘制一个基本黑色矩形,然后调用 function 将 canvas 旋转 0.5 弧度并绘制另一个矩形两次。 我还没有撤消我的旋转,所以第三个矩形实际上以 1 弧度旋转。

 let canvas = document.getElementById("canvas"); let ctx = canvas.getContext("2d"); function drawRotatedRectangle() { ctx.rotate(0.5); ctx.fillRect(0, 0, 60, 50); } // Draw base rectangle ctx.fillRect(0, 0, 60, 50); // Rotate and draw second rectangle ctx.fillStyle = "#FF0000"; drawRotatedRectangle(); // rotate and draw third rectangle ctx.fillStyle = "#00FF00"; drawRotatedRectangle();
 <canvas id="canvas"></canvas>

为了解决这个问题,我们修改了drawRotatedRectangle() function 以撤消它所做的所有平移和旋转:

 let canvas = document.getElementById("canvas"); let ctx = canvas.getContext("2d"); function drawRotatedRectangle() { ctx.rotate(0.5); ctx.fillRect(0, 0, 60, 50); ctx.rotate(-0.5); } // Draw base rectangle ctx.fillRect(0, 0, 60, 50); // Rotate and draw second rectangle ctx.fillStyle = "#FF0000"; drawRotatedRectangle(); // rotate and draw third rectangle ctx.fillStyle = "#00FF00"; drawRotatedRectangle();
 <canvas id="canvas"></canvas>

现在我们看到红色(隐藏)矩形和绿色矩形处于相同的角度。

围绕不同点旋转到原点

为了演示如何围绕不同位置旋转到原点,我们可以首先转换上下文原点的位置,然后旋转 canvas。 下面我将原点移动到基础矩形的中心,旋转 canvas 并在基础矩形上绘制一个旋转的矩形。 再次按照最近应用的顺序恢复平移和旋转。

 let canvas = document.getElementById("canvas"); let ctx = canvas.getContext("2d"); function drawRotatedRectangle() { // Move origin to center of rectangle ctx.translate(30, 25); // Rotate 0.5 radians ctx.rotate(0.5); // Draw rectangle where the center of the rectangle is the origin ctx.fillRect(-30, -25, 60, 50); // Undo our rotate ctx.rotate(-0.5); // Undo our translate ctx.translate(-30, -25); } // Draw base rectangle ctx.fillRect(0, 0, 60, 50); // Rotate and draw second rectangle ctx.fillStyle = "#FF0000"; drawRotatedRectangle(); // rotate and draw third rectangle ctx.fillStyle = "#00FF00"; drawRotatedRectangle();
 <canvas id="canvas"></canvas>

编辑 - 处理舍入错误

正如 Kaiido 在评论中提到的那样, rotate(a) function 将对输入进行四舍五入,因此只需执行反向rotate(-a) function 不会将您返回到原始转换。

他们建议的解决方案是使用setTransform()将变换矩阵设置为所需位置,在这些示例中,我们仅返回到 canvas 的原始变换,因此我们可以使用单位矩阵:

ctx.setTransform(1,0,0,1,0,0)

或者,您也可以使用save()restore()方法。 这些将类似于将 canvas 上下文的当前 state 推送到堆栈,当您restore()时,它将从堆栈中弹出最新的 state 并将您返回到先前的转换。 Jakob Jenkov 的这篇文章通过一些示例进一步解释了这种方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM