使用HTML5画布绘制圆形部分 - Math.PI

时间:2017-05-29 15:40:41

标签: javascript html5 canvas

我希望我有时间调试这个&调查在撰写此问题时弹出的可能答案,但我确实会尽快这样做;)

根据我的实际问题: 我试图沿着圆圈绘制弯曲的形状,但是我无法弄清楚这是一个愚蠢的错误还是需要象限处理的呐喊(nb:我对那些人来说很陌生) ; p)

据我所知,代码似乎可以正常工作。对于单个形状来说很好,但是当从循环中运行以构建形状时它会变得混乱:/

适用于一种形状的代码(&可能只在此位置;))



<!DOCTYPE html>
<html>
<body>

<canvas id="myCanvas2" width="300" height="300" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>

<script>
var graphValues = [1, 2, 3, 4, 5];

var c = document.getElementById("myCanvas2");
var ctx = c.getContext("2d");


// setup circle
// now onto drawing lines & stuff on a circle
var inner_radius = 20;
var radius = 80;
var point_size = 4;
var center_x = c.width/2;
var center_y = c.height/2;
var font_size = "20px";

// draw the circle
function drawCircle(){
    ctx.beginPath();
    ctx.arc(center_x, center_y, radius, 0, 2 * Math.PI);
    ctx.stroke();
}
drawCircle();

// draw the inner circle
function drawInnerCircle(){
    ctx.beginPath();
    ctx.arc(center_x, center_y, inner_radius, 0, 2 * Math.PI);
    ctx.stroke();
}
drawInnerCircle();


var horiStep360 = 360/graphValues.length-1; // way A
var step360 = 0;

// another helper to draw lines from the outer part of the circle to the center
function drawCurvedSection(angle){
  var nextAngle = angle + horiStep360;

  var innerCircle_start_x = center_x + inner_radius * Math.cos(-angle*Math.PI/180) * 1;
  var innerCircle_start_y = center_y + inner_radius * Math.sin(-angle*Math.PI/180) * 1;
  
  var innerCircle_end_x = center_x + inner_radius * Math.cos(-nextAngle*Math.PI/180) * 1;
  var innerCircle_end_y = center_y + inner_radius * Math.sin(-nextAngle*Math.PI/180) * 1;

  var outerCircle_start_x = center_x + radius * Math.cos(-angle*Math.PI/180) * 1;
  var outerCircle_start_y = center_y + radius * Math.sin(-angle*Math.PI/180) * 1;
  
  var outerCircle_end_x = center_x + radius * Math.cos(-nextAngle*Math.PI/180) * 1;
  var outerCircle_end_y = center_y + radius * Math.sin(-nextAngle*Math.PI/180) * 1;

  ctx.beginPath();
  ctx.arc(center_x, center_y, inner_radius, angle, nextAngle);
  
  ctx.arc(center_x, center_y, radius, angle, nextAngle);
  
  ctx.closePath();
  ctx.strokeStyle = 'blue';
  ctx.stroke();
  // TODO: fill with random/diff color
}


//step360 = 0; // reset before reuse
/*
graphValues.forEach(function(val){
  //drawPoint( 180 - step360, 1, val); // way A reverse ( draw counterclockwise )
  //drawPoint( step360, 1, val); // way A
  drawCurvedSection(step360);
  step360 += horiStep360;
});
*/
//drawCurvedSection(step360);



var nextAngle = step360 + horiStep360;

ctx.beginPath();

//ctx.arc(center_x, center_y, inner_radius, -step360, Math.PI-nextAngle); // PAIR A - original
ctx.arc(center_x, center_y, inner_radius, nextAngle*Math.PI/180, step360, true);
ctx.arc(center_x, center_y, radius, -step360, Math.PI-nextAngle); // PAIR A


// randomized color
ctx.fillStyle = '#' + ("000000" + Math.random().toString(16).slice(2, 8).toUpperCase()).slice(-6);
ctx.fill();
</script> 

</body>
</html>
&#13;
&#13;
&#13;

仍然是wip的代码:/ ..

&#13;
&#13;
<!DOCTYPE html>
<html>
<body>

<canvas id="myCanvas2" width="300" height="300" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>

<script>
var graphValues = [1, 2, 3, 4, 5];

var c = document.getElementById("myCanvas2");
var ctx = c.getContext("2d");


// setup circle
// now onto drawing lines & stuff on a circle
var inner_radius = 20;
var radius = 80;
var point_size = 4;
var center_x = c.width/2;
var center_y = c.height/2;
var font_size = "20px";

// draw the circle
function drawCircle(){
    ctx.beginPath();
    ctx.arc(center_x, center_y, radius, 0, 2 * Math.PI);
    ctx.stroke();
}
drawCircle();

// draw the inner circle
function drawInnerCircle(){
    ctx.beginPath();
    ctx.arc(center_x, center_y, inner_radius, 0, 2 * Math.PI);
    ctx.stroke();
}
drawInnerCircle();


var horiStep360 = 360/graphValues.length-1; // way A
var step360 = 0;

// another helper to draw lines from the outer part of the circle to the center
function drawCurvedSection(angle){
  var nextAngle = angle + horiStep360;

  /*
  var innerCircle_start_x = center_x + inner_radius * Math.cos(-angle*Math.PI/180) * 1;
  var innerCircle_start_y = center_y + inner_radius * Math.sin(-angle*Math.PI/180) * 1;
  
  var innerCircle_end_x = center_x + inner_radius * Math.cos(-nextAngle*Math.PI/180) * 1;
  var innerCircle_end_y = center_y + inner_radius * Math.sin(-nextAngle*Math.PI/180) * 1;

  var outerCircle_start_x = center_x + radius * Math.cos(-angle*Math.PI/180) * 1;
  var outerCircle_start_y = center_y + radius * Math.sin(-angle*Math.PI/180) * 1;
  
  var outerCircle_end_x = center_x + radius * Math.cos(-nextAngle*Math.PI/180) * 1;
  var outerCircle_end_y = center_y + radius * Math.sin(-nextAngle*Math.PI/180) * 1;
  */

  ctx.beginPath();
  /*
  ctx.arc(center_x, center_y, inner_radius, angle, nextAngle);
  ctx.arc(center_x, center_y, radius, angle, nextAngle);
  */
  ctx.arc(center_x, center_y, inner_radius, -step360, -Math.PI-nextAngle, true); // false :/
  ctx.arc(center_x, center_y, radius, -step360, Math.PI-nextAngle); // good ?
  
  ctx.closePath();
  //ctx.strokeStyle = 'blue';
  //ctx.stroke();
  // TODO: fill with random/diff color
  ctx.fillStyle = '#' + ("000000" + Math.random().toString(16).slice(2, 8).toUpperCase()).slice(-6);
  ctx.fill();
}


//step360 = 0; // reset before reuse

graphValues.forEach(function(val){
  //drawPoint( 180 - step360, 1, val); // way A reverse ( draw counterclockwise )
  //drawPoint( step360, 1, val); // way A
  drawCurvedSection(step360);
  step360 += horiStep360;
});
//drawCurvedSection(step360);


/*
var nextAngle = step360 + horiStep360;
ctx.beginPath();
//ctx.arc(center_x, center_y, inner_radius, -step360, Math.PI-nextAngle); // PAIR A - original
ctx.arc(center_x, center_y, inner_radius, nextAngle*Math.PI/180, step360, true);
ctx.arc(center_x, center_y, radius, -step360, Math.PI-nextAngle); // PAIR A
// randomized color
ctx.fillStyle = '#' + ("000000" + Math.random().toString(16).slice(2, 8).toUpperCase()).slice(-6);
ctx.fill();
*/
</script> 

</body>
</html>
&#13;
&#13;
&#13;

话虽如此,我会尝试一下,但我敢打赌,在弄清楚之前我必须做一些测试(并知道它为什么会出现故障以及如何解决它:))

祝所有S.O.读者非常好看&amp;晴天 ;) +

- 编辑 -

快速测试清楚地说明需要使用什么但不知道为什么它不起作用 - 我希望它很快就会清楚(目前它会画出五角形:/) - &GT;我的问题实际上是什么(除了知道我的代码在其他一些方面是错误的:

ctx.arc(100, 75, 50, (Math.PI*2/360)*<theAngle>, (Math.PI*2/360)*<theNextAngle>);

(是的,那对我来说很愚蠢,但现在我知道^^)

example attached below hosted on w3schools editor

以下代码段表明它似乎可以正常工作&#34;对于抚摸,但我还没有检查形状(..)

&#13;
&#13;
<!DOCTYPE html>
<html>
<body>

<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>

<script>

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(100, 75, 50, (Math.PI*2/360)*0, (Math.PI*2/360)*72);
ctx.strokeStyle = '#' + ("000000" + Math.random().toString(16).slice(2, 8).toUpperCase()).slice(-6);
ctx.stroke();

ctx.beginPath();
ctx.arc(100, 75, 50, (Math.PI*2/360)*72, (Math.PI*2/360)*144);
ctx.strokeStyle = '#' + ("000000" + Math.random().toString(16).slice(2, 8).toUpperCase()).slice(-6);
ctx.stroke();

ctx.beginPath();
ctx.arc(100, 75, 50, (Math.PI*2/360)*144, (Math.PI*2/360)*216);
ctx.strokeStyle = '#' + ("000000" + Math.random().toString(16).slice(2, 8).toUpperCase()).slice(-6);
ctx.stroke();

ctx.beginPath();
ctx.arc(100, 75, 50, (Math.PI*2/360)*216, (Math.PI*2/360)*288);
ctx.strokeStyle = '#' + ("000000" + Math.random().toString(16).slice(2, 8).toUpperCase()).slice(-6);
ctx.stroke();

ctx.beginPath();
ctx.arc(100, 75, 50, (Math.PI*2/360)*288, (Math.PI*2/360)*360);
ctx.strokeStyle = '#' + ("000000" + Math.random().toString(16).slice(2, 8).toUpperCase()).slice(-6);
ctx.stroke();
</script> 

</body>
</html>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:0)

你缺少的是函数ctx.arc

的最后一个参数
ctx.arc(x,y,radius,startAngle, endAngle, direction);

方向如果为true则告诉弧线逆时针绘制,否则顺时针方向错误绘制。

因此,如果你从内弧到外面画,你需要逆时针然后顺时针方向。

例如

&#13;
&#13;
const ctx = canvas.getContext("2d");
const cols = [
  "hsl(0,100%,50%)",
  "hsl(40,100%,50%)",
  "hsl(70,100%,50%)",
  "hsl(100,100%,50%)",
  "hsl(150,100%,50%)",
  "hsl(250,100%,50%)",
];
var startAng = 0;
var endAng = 1;
var innerRad = 50;
var outerRad = 100;
ctx.lineWidth = 3;
ctx.lineJoin = "round";
ctx.strokeStyle = "black";
function drawSlice(x,y,start,end,innerRad,outerRad,col){
    ctx.fillStyle = col;
    ctx.beginPath();
    ctx.arc(x,y,innerRad,end,start,true);
    ctx.arc(x,y,outerRad,start,end,false);
    ctx.closePath(); // to close path for stroke command
    ctx.fill();
    ctx.stroke();
}
var count = 0;
for(var i = 0; count  < cols.length; i += 1){
    drawSlice(200,200,i,i+0.9,innerRad,outerRad,cols[count++])

}
&#13;
<canvas id=canvas width= 400 height = 400></canvas>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

所以,正确答案是......

(..)
ctx.arc(center_x, center_y, inner_radius, (Math.PI*2/360)*nextAngle, (Math.PI*2/360)*angle, true);
ctx.arc(center_x, center_y, radius, (Math.PI*2/360)*angle, (Math.PI*2/360)*nextAngle, false);
(..)

- 编辑 -

为了更清楚地澄清,我忘记在使用它们之前将度数转换为弧度:/

var deg = angle; // angle in °
var rads = Math.PI/180*deg; // simpler yet same as (Math.PI*2/360)*deg

提醒一下,(Math.PI*2/360)*angleDegree只是获得角度和角度的度数。下一个角色,而诀窍&#39;是记住在传递可选方向参数时切换参数顺序。 因此,函数调用中所需的公式为:

ctx.arc(x, y, rad, (Math.PI*2/360)*2ndAngle, (Math.PI*2/360)*1stangle, true);
ctx.arc(x, y, outRad, (Math.PI*2/360)*1stangle, (Math.PI*2/360)*2ndAngle, false);

使用stroke(),这将呈现:

&#13;
&#13;
<!DOCTYPE html>
<html>
<body>

<canvas id="myCanvas2" width="300" height="300" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>

<script>
var graphValues = [1, 2, 3, 4, 5];

var c = document.getElementById("myCanvas2");
var ctx = c.getContext("2d");


// setup circle
// now onto drawing lines & stuff on a circle
var inner_radius = 20;
var radius = 80;
var point_size = 4;
var center_x = c.width/2;
var center_y = c.height/2;
var font_size = "20px";

// draw the circle
function drawCircle(){
    ctx.beginPath();
    ctx.arc(center_x, center_y, radius, 0, 2 * Math.PI);
    ctx.stroke();
}
//drawCircle();

// draw the inner circle
function drawInnerCircle(){
    ctx.beginPath();
    ctx.arc(center_x, center_y, inner_radius, 0, 2 * Math.PI);
    ctx.stroke();
}
//drawInnerCircle();


//var horiStep360 = 360/graphValues.length-1; // made it work when testing single one ?!
var horiStep360 = 360/graphValues.length; // to gett ful 36° per item
// for 5 values:
// 0° -> 72°
// 72° -> 144°
// 144° -> 216°
// 216° -> 288°
// 288° -> 360°
var step360 = 0;

// another helper to draw lines from the outer part of the circle to the center
function drawCurvedSection(angle){
  var nextAngle = angle + horiStep360;
  console.log('current angle: ' + angle + '° & next angle: ' + nextAngle + '°');

  /*
  var innerCircle_start_x = center_x + inner_radius * Math.cos(-angle*Math.PI/180) * 1;
  var innerCircle_start_y = center_y + inner_radius * Math.sin(-angle*Math.PI/180) * 1;
  
  var innerCircle_end_x = center_x + inner_radius * Math.cos(-nextAngle*Math.PI/180) * 1;
  var innerCircle_end_y = center_y + inner_radius * Math.sin(-nextAngle*Math.PI/180) * 1;

  var outerCircle_start_x = center_x + radius * Math.cos(-angle*Math.PI/180) * 1;
  var outerCircle_start_y = center_y + radius * Math.sin(-angle*Math.PI/180) * 1;
  
  var outerCircle_end_x = center_x + radius * Math.cos(-nextAngle*Math.PI/180) * 1;
  var outerCircle_end_y = center_y + radius * Math.sin(-nextAngle*Math.PI/180) * 1;
  */

  ctx.beginPath();
  
  //ctx.arc(center_x, center_y, inner_radius, angle, nextAngle);
  //ctx.arc(center_x, center_y, radius, angle, nextAngle);
  //ctx.arc(center_x, center_y, inner_radius, -step360, -Math.PI-nextAngle, true); // false
  //ctx.arc(center_x, center_y, radius, -step360, Math.PI-nextAngle); // good ?
  //ctx.arc(center_x, center_y, inner_radius, -angle, -nextAngle, true); // false
  //ctx.arc(center_x, center_y, radius, -angle, -nextAngle); // good ?
  
  // debug
  //ctx.arc(center_x, center_y, inner_radius, angle*Math.PI*2/180, nextAngle*Math.PI*2/180, true);
  //ctx.arc(center_x, center_y, radius, angle*Math.PI*2/180, nextAngle*Math.PI*2/180, false);
  // R: invert the angle & nextAngle AS WELL AS set optional direction parameter !!! -> WORKS !!!!
  ctx.arc(center_x, center_y, inner_radius, (Math.PI*2/360)*nextAngle, (Math.PI*2/360)*angle, true);
  ctx.arc(center_x, center_y, radius, (Math.PI*2/360)*angle, (Math.PI*2/360)*nextAngle, false);
  
  ctx.closePath();
  //ctx.strokeStyle = 'blue';
  ctx.strokeStyle = '#' + ("000000" + Math.random().toString(16).slice(2, 8).toUpperCase()).slice(-6);
  ctx.stroke();
  // TODO: fill with random/diff color
  //ctx.fillStyle = '#' + ("000000" + Math.random().toString(16).slice(2, 8).toUpperCase()).slice(-6);
  //ctx.fill();
}


//step360 = 0; // reset before reuse

graphValues.forEach(function(val){
  //drawPoint( 180 - step360, 1, val); // way A reverse ( draw counterclockwise )
  //drawPoint( step360, 1, val); // way A
  drawCurvedSection(step360);
  step360 += horiStep360;
});

//drawCurvedSection(step360); - to be called manually to step through & see where/why glitch begins
function debugDrawCurvedSection(){
  drawCurvedSection(step360);
  step360 += horiStep360;
}
//debugDrawCurvedSection(); // ok ..
//debugDrawCurvedSection(); // fucked up
//debugDrawCurvedSection();

/*
var nextAngle = step360 + horiStep360;
ctx.beginPath();
//ctx.arc(center_x, center_y, inner_radius, -step360, Math.PI-nextAngle); // PAIR A - original
ctx.arc(center_x, center_y, inner_radius, nextAngle*Math.PI/180, step360, true);
ctx.arc(center_x, center_y, radius, -step360, Math.PI-nextAngle); // PAIR A
// randomized color
ctx.fillStyle = '#' + ("000000" + Math.random().toString(16).slice(2, 8).toUpperCase()).slice(-6);
ctx.fill();
*/

// manual tests
/*
ctx.beginPath();
ctx.arc(center_x, center_y, inner_radius, 0, 2, true);
ctx.arc(center_x, center_y, radius, 0, 2, false);
// randomized color
ctx.fillStyle = '#' + ("000000" + Math.random().toString(16).slice(2, 8).toUpperCase()).slice(-6);
ctx.fill();
*/
</script> 

</body>
</html>
&#13;
&#13;
&#13;

使用fill(),这将呈现:

&#13;
&#13;
<!DOCTYPE html>
<html>
<body>

<canvas id="myCanvas2" width="300" height="300" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>

<script>
var graphValues = [1, 2, 3, 4, 5];

var c = document.getElementById("myCanvas2");
var ctx = c.getContext("2d");


// setup circle
// now onto drawing lines & stuff on a circle
var inner_radius = 20;
var radius = 80;
var point_size = 4;
var center_x = c.width/2;
var center_y = c.height/2;
var font_size = "20px";

// draw the circle
function drawCircle(){
    ctx.beginPath();
    ctx.arc(center_x, center_y, radius, 0, 2 * Math.PI);
    ctx.stroke();
}
//drawCircle();

// draw the inner circle
function drawInnerCircle(){
    ctx.beginPath();
    ctx.arc(center_x, center_y, inner_radius, 0, 2 * Math.PI);
    ctx.stroke();
}
//drawInnerCircle();


//var horiStep360 = 360/graphValues.length-1; // made it work when testing single one ?!
var horiStep360 = 360/graphValues.length; // to gett ful 36° per item
// for 5 values:
// 0° -> 72°
// 72° -> 144°
// 144° -> 216°
// 216° -> 288°
// 288° -> 360°
var step360 = 0;

// another helper to draw lines from the outer part of the circle to the center
function drawCurvedSection(angle){
  var nextAngle = angle + horiStep360;
  console.log('current angle: ' + angle + '° & next angle: ' + nextAngle + '°');

  /*
  var innerCircle_start_x = center_x + inner_radius * Math.cos(-angle*Math.PI/180) * 1;
  var innerCircle_start_y = center_y + inner_radius * Math.sin(-angle*Math.PI/180) * 1;
  
  var innerCircle_end_x = center_x + inner_radius * Math.cos(-nextAngle*Math.PI/180) * 1;
  var innerCircle_end_y = center_y + inner_radius * Math.sin(-nextAngle*Math.PI/180) * 1;

  var outerCircle_start_x = center_x + radius * Math.cos(-angle*Math.PI/180) * 1;
  var outerCircle_start_y = center_y + radius * Math.sin(-angle*Math.PI/180) * 1;
  
  var outerCircle_end_x = center_x + radius * Math.cos(-nextAngle*Math.PI/180) * 1;
  var outerCircle_end_y = center_y + radius * Math.sin(-nextAngle*Math.PI/180) * 1;
  */

  ctx.beginPath();
  
  //ctx.arc(center_x, center_y, inner_radius, angle, nextAngle);
  //ctx.arc(center_x, center_y, radius, angle, nextAngle);
  //ctx.arc(center_x, center_y, inner_radius, -step360, -Math.PI-nextAngle, true); // false
  //ctx.arc(center_x, center_y, radius, -step360, Math.PI-nextAngle); // good ?
  //ctx.arc(center_x, center_y, inner_radius, -angle, -nextAngle, true); // false
  //ctx.arc(center_x, center_y, radius, -angle, -nextAngle); // good ?
  
  // debug
  //ctx.arc(center_x, center_y, inner_radius, angle*Math.PI*2/180, nextAngle*Math.PI*2/180, true);
  //ctx.arc(center_x, center_y, radius, angle*Math.PI*2/180, nextAngle*Math.PI*2/180, false);
  // R: invert the angle & nextAngle AS WELL AS set optional direction parameter !!! -> WORKS !!!!
  ctx.arc(center_x, center_y, inner_radius, (Math.PI*2/360)*nextAngle, (Math.PI*2/360)*angle, true);
  ctx.arc(center_x, center_y, radius, (Math.PI*2/360)*angle, (Math.PI*2/360)*nextAngle, false);
  
  ctx.closePath();
  //ctx.strokeStyle = 'blue';
  //ctx.strokeStyle = '#' + ("000000" + Math.random().toString(16).slice(2, 8).toUpperCase()).slice(-6);
  //ctx.stroke();
  // TODO: fill with random/diff color
  ctx.fillStyle = '#' + ("000000" + Math.random().toString(16).slice(2, 8).toUpperCase()).slice(-6);
  ctx.fill();
}


//step360 = 0; // reset before reuse

graphValues.forEach(function(val){
  //drawPoint( 180 - step360, 1, val); // way A reverse ( draw counterclockwise )
  //drawPoint( step360, 1, val); // way A
  drawCurvedSection(step360);
  step360 += horiStep360;
});

//drawCurvedSection(step360); - to be called manually to step through & see where/why glitch begins
function debugDrawCurvedSection(){
  drawCurvedSection(step360);
  step360 += horiStep360;
}
//debugDrawCurvedSection(); // ok ..
//debugDrawCurvedSection(); // fucked up
//debugDrawCurvedSection();

/*
var nextAngle = step360 + horiStep360;
ctx.beginPath();
//ctx.arc(center_x, center_y, inner_radius, -step360, Math.PI-nextAngle); // PAIR A - original
ctx.arc(center_x, center_y, inner_radius, nextAngle*Math.PI/180, step360, true);
ctx.arc(center_x, center_y, radius, -step360, Math.PI-nextAngle); // PAIR A
// randomized color
ctx.fillStyle = '#' + ("000000" + Math.random().toString(16).slice(2, 8).toUpperCase()).slice(-6);
ctx.fill();
*/

// manual tests
/*
ctx.beginPath();
ctx.arc(center_x, center_y, inner_radius, 0, 2, true);
ctx.arc(center_x, center_y, radius, 0, 2, false);
// randomized color
ctx.fillStyle = '#' + ("000000" + Math.random().toString(16).slice(2, 8).toUpperCase()).slice(-6);
ctx.fill();
*/
</script> 

</body>
</html>
&#13;
&#13;
&#13;

谢谢大家,我希望这有助于其他人:)

相关问题