有没有一种方法可以更改CanvasRenderingContext2D.arc,使其显示为馅饼?

时间:2019-05-15 07:04:07

标签: javascript html5 canvas html5-canvas

我已经使用HTML Canvas进行了数周的实验,并且使用.arc来制作圆圈,但是当圆圈不完整时,它不会像一块馅饼。相反,它使用了一端到另一端的最短距离,并填充了其余部分!有没有办法将其显示为馅饼? 这是一个使用.arc的示例:

<html>
<head>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.arc(100, 75, 50, 0, 2) //supposedly radians for 2
ctx.stroke();
ctx.fillStyle = "black";
ctx.fill();
</head>
<body>
<canvas id="canvas" width="1000" height="600"></canvas>
</body>
</html>

1 个答案:

答案 0 :(得分:0)

因此,发生的情况是.arc()从您提供的x和y坐标创建了一个成角度的路径。您需要做的是:

  • 将“绘图指针”移动到要放置圆圈的位置
  • 从该位置开始做“路径”,该位置是圆的中心
  • 绘制实际的圆弧
  • 返回您的圈子以关闭该路径。

以下代码说明了一个可行的示例:

const WIDTH   = 100;
const HEIGHT  = 100;
const RADIUS  = 50;
const canvas  = document.createElement('canvas');
const context = canvas.getContext('2d');
canvas.width  = WIDTH;
canvas.height = HEIGHT;

document.body.appendChild(canvas);

//  identify center of your circle for learning purposes
//  let's use the center of the canvas:
const [dx, dy] = [WIDTH / 2, HEIGHT / 2];
context.fillStyle = 'orange';
context.fillRect(dx, dy, 5, 5);

//  clean / begin your paths
context.beginPath();

//  move to (and start your path to) your position:
context.moveTo(dx, dy);

//  create a circle using the dx,dy as the center of the circle:
const startAngleInRadians = 0;
const endAngleInRadians   = Math.PI * 0.5;
const goAntiClockwise     = false;
context.arc(dx, dy, RADIUS, startAngleInRadians, endAngleInRadians, goAntiClockwise);

//  move back to your position (not required if you only draw 1 pie since your paths dont change):
context.moveTo(dx, dy);

//  let's fill our pie with a pink color!:
context.fillStyle = '#FF00FF55';
context.fill();

为说明实际情况,我制作了一个简单的画布动画:

const WIDTH   = 200;
const HEIGHT  = 200;
const RADIUS  = 50;
const canvas  = document.createElement('canvas');
const context = canvas.getContext('2d');
const [dx, dy] = [0, 0];

canvas.width  = WIDTH;
canvas.height = HEIGHT;

document.body.appendChild(canvas);

context.strokeStyle = 'red';

function sleep(timeout) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(true);
    }, timeout);
  });
}

async function showHowItWorks() {
  //  move from arc center to the arc start position:
  for (let i=0; i<RADIUS; i++) {
    context.beginPath();
    context.moveTo(dx, dy);
    context.lineTo(dx + i, dy);
    context.stroke();
    await sleep(50);
  }

  //  draw the arc from start position to arc end:
  const angle = Math.PI * 0.5;
  for (let i=0; i<angle; i+=0.05) {
    context.beginPath();
    context.arc(dx, dy, RADIUS, 0, i, false);
    context.stroke();
    await sleep(50);
  }

  //  move from arc end back to the arc center:
  for (let i=50; i>=0; i--) {
    context.moveTo(dx, dy + RADIUS);
    context.lineTo(dx, dy + i);
    context.stroke();
    await sleep(50);
  }
}

showHowItWorks();

当然,有一些缺陷:我不确定.arc()命令是将“绘图指针”(如.moveTo())移动还是从位置向弧形移动{{1 }}-。

在第一种情况下,指针从您的中心位置跳到弧线。在第二种情况下,它实际上创建了一条从您的中心到弧线的线。但是无论如何,在大多数情况下,两种方法都会给您相同的最终结果。