Search code examples
htmlcanvashtml5-canvaskineticjskonvajs

How to get width & height of drawn arc(s) in HTML5 Canvas?


Here I have drawn some arcs using Konvajs library, but I cannot get their width and height after the objects have been drawn, How can I do that? for quick read of code:

function drawSurface(idnumber, radius, x, y, startAngleParam, endAngleParam) {
var borderbold = 5;
var surface;
if (typeof startAngleParam !== 'undefined') {
    surface = new Konva.Shape({
        x: x,
        y: y,
        fill: '#ccc',
        stroke: "#ccc",
        strokeWidth: 8,
        id: idnumber,
        opacity: 1,
        drawFunc: function (context) {
            var startAngle = startAngleParam * Math.PI;
            var endAngle = (startAngleParam + 0.5 + endAngleParam) * Math.PI;
            var counterClockwise = false;
            context.beginPath();
            context.arc(0, 0, radius, startAngle, endAngle, counterClockwise);
            context.setAttr("lineWidth", borderbold);
            context.stroke();
            context.fillStrokeShape(this);
        }
    });
}
else {
    surface = new Konva.Circle({
        x: x,
        y: y,
        radius: radius,
        fill: '#ccc',
        strokeWidth: 3,
        id: idnumber,
        opacity: 1
    });
}
return surface;
}

Please support your answer with a code example.


Solution

  • Find the bounding box of your arc and then calculate the width & height from the bounding box.

    enter image description here

    Geometrically, the only 5 possible bounding box corners are:

    • the arc centerpoint,
    • the point on the arc (if any) at 0 degrees (0 radians),
    • the point on the arc (if any) at 90 degrees (PI/2 radians),
    • the point on the arc (if any) at 180 degrees (PI radians),
    • the point on the arc (if any) at 270 degrees (PI*3/2 radians),

    From these possible bounding box points, find the minimum X, minimum Y, maximum X & maximum Y. The [minX,minY] will be the top left corner of the bounding box. The [maxX,maxY] will be the bottom right corner of the bounding box.

    Your arc width will be maxX-minX and height will be maxY-minY.

    Here's example code and a Demo:

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var cw=canvas.width;
    var ch=canvas.height;
    
    
    var PI=Math.PI;
    var cx=150;
    var cy=150;
    var radius=75;
    var startAngle=-PI/4;
    var endAngle=PI/3;
    
    ctx.beginPath();
    ctx.moveTo(cx,cy);
    ctx.arc(cx,cy,radius,startAngle,endAngle);
    ctx.closePath();
    ctx.fillStyle='skyblue';
    ctx.fill();
    ctx.strokeStyle='lightgray';
    ctx.lineWidth=3;
    ctx.stroke();
    
    var bb=arcBounds(cx,cy,radius,startAngle,endAngle);
    ctx.strokeStyle='red';
    ctx.lineWidth=1;
    ctx.strokeRect(bb.x,bb.y,bb.width,bb.height);
    
    
    function arcBounds(cx,cy,radius,startAngle,endAngle){
      var minX=1000000;
      var minY=1000000;
      var maxX=-1000000;
      var maxY=-1000000;
    
      var possibleBoundingPoints=[]
      // centerpoint
      possibleBoundingPoints.push({x:cx,y:cy});
      // starting angle
      possibleBoundingPoints.push(arcpoint(cx,cy,radius,startAngle));
      // ending angle
      possibleBoundingPoints.push(arcpoint(cx,cy,radius,endAngle));
      // 0 radians
      if(0>=startAngle && 0<=endAngle){
        possibleBoundingPoints.push(arcpoint(cx,cy,radius,0));
      }
      // PI/2 radians
      var angle=PI/2;
      if(angle>=startAngle && angle<=endAngle){
        possibleBoundingPoints.push(arcpoint(cx,cy,radius,angle));
      }
      // PI radians
      var angle=PI;
      if(angle>=startAngle && angle<=endAngle){
        possibleBoundingPoints.push(arcpoint(cx,cy,radius,angle));
      }
      // PI*3/2 radians
      var angle=PI*3/2;
      if(angle>=startAngle && angle<=endAngle){
        possibleBoundingPoints.push(arcpoint(cx,cy,radius,angle));
      }
    
      for(var i=0;i<possibleBoundingPoints.length;i++){
        var pt=possibleBoundingPoints[i];
        if(pt.x<minX){minX=pt.x;}
        if(pt.y<minY){minY=pt.y;}
        if(pt.x>maxX){maxX=pt.x;}
        if(pt.y>maxY){maxY=pt.y;}
      }
    
      return({ x:minX, y:minY, width:maxX-minX, height:maxY-minY });
    
    }
    
    
    function arcpoint(cx,cy,radius,angle){
      var x=cx+radius*Math.cos(angle);
      var y=cy+radius*Math.sin(angle);
      return({x:x,y:y});
    }
    body{ background-color: ivory; }
    #canvas{border:1px solid blue;}
    <canvas id="canvas" width=300 height=300></canvas>