请帮我弄清楚这颗星是如何在帆布上制作的

时间:2015-11-23 05:58:27

标签: javascript math canvas trigonometry

我在网上找到了这个代码,我想弄明白。

window.onload = function(){
	var canvas = document.getElementById("canvas"),
		ctx = canvas.getContext("2d");

	function drawStar(cx, cy, spikes, outerRadius, innerRadius){
		var rot = Math.PI / 2 * 3;
		var x = cx;
		var y = cy;
		var step = Math.PI / spikes;

		ctx.strokeStyle = "#000";
		ctx.beginPath();
		ctx.moveTo(cx, cy - outerRadius) //100 - 30

		for(i = 0; i < spikes; i++){
			$(".display").append(Math.cos(rot) +" , ")
			x = cx + Math.cos(rot) * outerRadius;
			y = cy + Math.sin(rot) * outerRadius;
			console.log("x : ", x, " y : ", y)
			ctx.lineTo(x,y);
			rot += step;

			x = cx + Math.cos(rot) * innerRadius;
			y = cy + Math.sin(rot) * innerRadius;
			ctx.lineTo(x,y);
			rot+= step;
		}

		ctx.lineTo(cx, cy- outerRadius);
		ctx.closePath();
		ctx.lineWidth = 1;
		ctx.strokeStyle = "blue";
		ctx.stroke()
		ctx.beginPath();
		ctx.arc(cx,cy,2, 0, (Math.PI * 2), true);
		ctx.fillStyle = "red";
		ctx.fill()
		ctx.closePath();
	}

	drawStar(75, 100, 5,45, 15) //cx,cy,spikes, outerRadius, innerRadius
}
canvas{
	background: #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<canvas id="canvas" width="400" height="400"></canvas>
<div class="display"></div>

我看到它说var rot = Math.PI / 2 * 3我将把它想象成270度角,因为90 * 3 = 270.我需要帮助弄清楚它们是如何得到星的右上角的点。我认为是outerRadius

他们在右上角点x = cx + Math.cos(rot) * outerRadius;(试图获得右上角点)是54度的'腐烂'吗? ..我想(Math.PI / 5) * 180 / Math.PI 5来自步变量...等于36,所以我做了90度 - 36得到54.我希望我把它弄清楚吧?我不确定为什么他们使用270度。你能详细说明吗?我不确定为什么他们使用var rot = Math.PI / 2 * 3如果我玩nums一点点我得到垃圾。我假设他们正在使用它来获得点组成的角度但是我很难把这些碎片放在一起。

编辑:我把红点放在中间,以帮助我测量点到中心的角度。

2 个答案:

答案 0 :(得分:0)

虽然这很直接:

  • 画布中的角度计算如下:0度处于水平位置,顺时针方向,因此1.5 PI(270度)位于顶部。

    cx + Math.cos(rot) * outerRadius = 0
    cy + Math.sin(rot) * outerRadius = outerRadius
    
  • 2 * PI是一个完整的圆圈,因此要绘制每个长矛,您将每隔2 * PI/spikes绘制一次。您可以看到rot每次增加两倍PI/spikes,一个用于内部点,第二个用于外部点。

答案 1 :(得分:0)

我在你的演示中添加了一些文字,希望它有助于回答你的问题。

首先,你假设Math.PI / 2 * 3与弧度达到270度相同是正确的。为了说明,我已将其更改为270 * Math.PI / 180,这会产生相同的结果,并且可能更直观易读。

它从270开始的原因是因为如果您将画布中的旋转视为时钟,则0度将恰好位于3点钟位置,或者相对于您的上下文点位于右侧。然后,如果旋转270度,则在上下文点正上方12点处。

在您的代码中,开头的moveTo和循环中的第一个点完全相同(请参阅演示如何使用Init上下文点和0.a相同)。然后,当rot通过添加step递增时,您会看到如何按顺序绘制点。从外半径移动到内半径。

var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");

function drawStar(cx, cy, spikes, outerRadius, innerRadius) {
    var rot = 270 * Math.PI / 180;
    var x = cx;
    var y = cy;
    var step = Math.PI / spikes;
 
    ctx.strokeStyle = "#000";
    ctx.beginPath();
    ctx.moveTo(cx, cy - outerRadius) //100 - 30
    ctx.fillText('Init context point: x: ' + cx + ', y: ' + (cy - outerRadius), cx, cy - outerRadius - 10);

    for (i = 0; i < spikes; i++) {
        $(".display").append(Math.cos(rot) + " , ")
        x = cx + Math.cos(rot) * outerRadius;
        y = cy + Math.sin(rot) * outerRadius;
        console.log("x : ", x, " y : ", y)
        ctx.lineTo(x, y);
        ctx.fillStyle = 'green';
        ctx.fillText('(' + i + '.a), ' + rot * (180/Math.PI) + '°', x, y);
        rot += step;

        x = cx + Math.cos(rot) * innerRadius;
        y = cy + Math.sin(rot) * innerRadius;
        ctx.fillStyle = 'yellow';
        ctx.fillText('(' + i + '.b), ' + rot * (180/Math.PI) + '°', x, y);
        ctx.lineTo(x, y);
        rot += step;
    }
    // I've commented this out since closePath() in the next line will do 
    // the same as drawing the last line back to the initial context point.
    // ctx.lineTo(cx, cy - outerRadius);
    ctx.closePath();
    ctx.lineWidth = 1;
    ctx.strokeStyle = "blue";
    ctx.stroke()
    ctx.beginPath();
    ctx.arc(cx, cy, 2, 0, (Math.PI * 2), true);
    ctx.fillStyle = "red";
    ctx.fillText("x: " + cx + ', y: ' + cy, cx, cy);
    ctx.fill()
    ctx.closePath();
}

drawStar(150, 150, 5, 100, 50) //cx,cy,spikes, outerRadius, innerRadius
canvas{
	background: #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<canvas id="canvas" width="400" height="400"></canvas>
<div class="display"></div>