简体   繁体   中英

How to convert an Arc into a Line with HTML5 Canvas?

I would like to animate a circle into a line with the radius equaling the width, and I am wondering how I can do this with an Arc? Or perhaps there is a better way?

From 在此处输入图片说明

To 在此处输入图片说明

Here's my arc:

function drawStar(x,y,size,scale,opacity,ctx){
  ctx.save();
  ctx.beginPath();
  ctx.arc(x,y,size+scale,0,size+scale * Math.PI,false);
  ctx.globalAlpha = opacity
  ctx.closePath();
  setFillStyle('rgb(255,237,219)',ctx);
  ctx.fill()
  ctx.restore();
}

I tried using ctx.scale(n,1), however it does not keep the same radius(width) and it scales the collection of arcs as a whole (zoom in effect).

Use instead a wide line-width value with "round" lineCap and stroke() :

 var ctx = c.getContext("2d"); ctx.lineWidth = 50; ctx.lineCap = "round"; ctx.moveTo(45 , 25); ctx.lineTo(45.5, 25); // in IE11 this must be slightly offset ctx.moveTo( 45, 100); ctx.lineTo(150, 100); ctx.stroke(); 
 <canvas id=c></canvas> 

Remember beginPath() for animation.

You could draw the left and right halves of a circle using arc , then do a fillRect in between to connect them.

Edit: To elaborate on what I said earlier:

function init() {
  let canvas = document.getElementById('myCanvas');

  canvas.width = 400;
  canvas.height = 400;
  canvas.style.width = "400px";
  canvas.style.height = "400px";

  let ctx = canvas.getContext("2d");

  function fillArc(ctx, cx, cy, r, startDeg, endDeg) {
    ctx.beginPath();
    ctx.arc(cx, cy, r, startDeg * Math.PI / 180, endDeg * Math.PI / 180);
    ctx.fill();
  }

  function fillOval(ctx, cx, cy, r, sideLength, skipFirstArc) {
    if (!skipFirstArc) {
      fillArc(ctx, cx, cy, r, 90, 270);
    }

    ctx.fillRect(cx, cy - r, sideLength, r * 2);
    fillArc(ctx, cx + sideLength, cy, r, 270, 90);
  }

  let sideLength = 0;
  ctx.fillStyle = 'red';

  function animateOval() {
    if (sideLength === 100) {
      ctx.clearRect(0, 0, 400, 400);
    }
    else {
      fillOval(ctx, 30, 30, 25, sideLength, sideLength > 0);
    }

    ++sideLength;

    if (sideLength > 100) {
      sideLength = 0;
    }
  }

  setInterval(animateOval, 16);
}

Here's a Plunker with the above code running: http://plnkr.co/edit/vNqoUjPKg2lqC7JtYuEb?p=preview

You can use Bezier Curves to 'transform' your arc.

There's some math involved in calculating the perfect ends of your stretched circle but I guessed and tweaked my numbers.

 var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); ctx.beginPath(); ctx.moveTo(40, 20); ctx.lineTo(100, 20); ctx.bezierCurveTo(130, 20, 130, 60, 100, 60); ctx.lineTo(40, 60); ctx.bezierCurveTo(10, 60, 10, 20, 40, 20); ctx.stroke(); ctx.fill(); ctx.closePath(); ctx.beginPath(); ctx.moveTo(40, 80); ctx.bezierCurveTo(68, 80, 68, 120, 40, 120); ctx.bezierCurveTo(12, 120, 12, 80, 40, 80); ctx.fill(); ctx.stroke(); 
 <canvas id="myCanvas"></canvas> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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