Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

creating a circle of bars with HTML5 canvas, but the space between bars is uneven

I'm trying to create a circular progressbar(though it wouldn't be a bar anymore, would it?). Around this cricle there are thin bars perpendicular to the circle. Now the problem is, my code doesn't generate there bars in an even spacing. Here's the code and an image of the result: uneven perpendicular lines to the circle

function MH5PB(canvasId,            //the id of the canvas to draw the pb on
                value,              //a float value, representing the progress(ex: 0.3444)
                background,         //the background color of the pb(ex: "#ffffff")
                circleBackground,   //the background color of the bars in the circles
                integerColor,       //the color of the outer circle(or the int circle)
                floatColor          //the color of the inner circle(or the float circle)
                )
{
    var canvas = document.getElementById(canvasId);
    var context = canvas.getContext("2d");
    var canvasWidth = canvas.width;
    var canvasHeight = canvas.height;
    var radius = Math.min(canvasWidth, canvasHeight) / 2;
    var numberOfBars = 72;
    var barThickness = 2;

    //margin from the borders, and also the space between the two circles
    var margin = parseInt(radius / 12.5) >= 2 ? parseInt(radius / 12.5) : 2; 

    //the thickness of the int circle and the float circle
    var circleThickness = parseInt((radius / 5) * 2);

    //the outer radius of the int circle
    var intOuterRadius = radius - margin;
    //the inner radius of the int circle
    var intInnerRadius = radius - margin - circleThickness;

    //the outer radius of the float circle
    var floatOuterRadius = intOuterRadius - margin - circleThickness;
    //the inner radius of the float circle
    var floatInnerRadius = floatOuterRadius - circleThickness;

    //draw a bar, each degreeStep degrees
    var intCircleDegreeStep = 5;
                                    // ((2 * Math.PI * intOuterRadius) / (barThickness + 10)) //
                                    //  this area is the total number of required bars  //
                                    //  to fill the intCircle.1px space between each bar//
    var floatCircleDegreeStep = 360 / ((2 * Math.PI * floatOuterRadius) / (barThickness + 10));        

    context.lineWidth = barThickness;
    context.strokeStyle = circleBackground;
    //draw the bg of the outer circle
    for(i = 90; i < 450; i+=intCircleDegreeStep)
    {
        //since we want to start from top, and move cw, we have to map the degree
        //in the loop
        cxOuter = Math.floor(intOuterRadius * Math.cos(i) + radius);
        cyOuter = Math.floor(intOuterRadius * Math.sin(i) + radius);
        cxInner = Math.floor(intInnerRadius * Math.cos(i) + radius);
        cyInner = Math.floor(intInnerRadius * Math.sin(i) + radius);
        context.moveTo(cxOuter, cyOuter);
        context.lineTo(cxInner, cyInner);
        context.stroke();
    }
}

EDIT: Oh, and also the lines aren't anti-aliased. Do you know why? I should also explain that this progressbar consists of two parts. An outer circle (visible in the provided image) and an inner circle. The outer circle is the amount of the integer part of the percentage (i.e. 45 in 45.98%) and the inner circle is the amount of the not integer part of the percentage (i.e. 98 in 45.98%). Hence you now know what intCircle and floatCircle are :)

like image 813
Milad.Nozari Avatar asked May 19 '13 17:05

Milad.Nozari


1 Answers

It appears you are passing degrees to Math.sin and Math.cos. These functions expect radians. For example,

// i degrees to radians.
Math.sin(i * (Math.PI / 180)); 
like image 166
veritasetratio Avatar answered Sep 22 '22 03:09

veritasetratio