2013-05-19 14 views
7

Próbuję utworzyć okrągły pasek postępu (choć nie byłby to już pasek, prawda?). Wokół tego cricle są cienkie paski prostopadłe do koła. Problem polega na tym, że mój kod nie generuje prętów w równym odstępie. Oto kod i wizerunek wyniku: uneven perpendicular lines to the circleTworzenie okręgu pasków z płótnem HTML5, ale odstęp między kreskami jest nierówny

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, a także linie nie są wygładzane. Wiesz dlaczego? Należy również wyjaśnić, że ten pasek postępu składa się z dwóch części. Zewnętrzny okrąg (widoczny na załączonym obrazku) i wewnętrzny okrąg. Zewnętrzny okrąg jest wielkością całkowitej części wartości procentowej (to jest 45 w 45,98%), a wewnętrzny okrąg jest wielkością niecałkowitej części wartości procentowej (to jest 98 w 45,98%). Stąd teraz wiesz, czym jest intCircle i floatCircle :)

+0

tylko małe przypuszczenie tutaj: Twój numer barów nie może być lubiany przez rzeczy, więc to kondensacyjny je produkować dobre kółko? Spekulacja –

+0

Dzięki za zainteresowanie Ian. Cóż, nie jestem pewien. Podejrzewam, że ma to coś wspólnego z funkcjami sinus i cosinus, wiesz. Ponieważ tworzą one podwójną wartość, ilość dodawana do następnych współrzędnych jest nierównomierna. Ale nie wiem, jak to naprawić: D A przy okazji, dzięki za edycję;) –

+0

Nigdy wcześniej nie rysowałem niczego w JS, więc niestety nie pomogę tutaj. Weź jednak udział w przeglądzie. :) –

Odpowiedz

5

Wygląda na to, że przechodzisz stopnie do Math.sin i Math.cos. Te funkcje oczekują radianów. Na przykład,

// i degrees to radians. 
Math.sin(i * (Math.PI/180)); 
+2

To, plus * wszystkie * rzeczy zaokrąglenia/ścięcia muszą iść. – Pointy

+0

O mój Boże! Wstyd mi za to zaniedbanie. Wielkie dzięki, zadziałało. ale problem anty-aliasingu jest problemem. Ponieważ płótno ma domyślnie, czy wiesz, dlaczego nie działa w tym przypadku? –

+1

@MNVOH pozbądź się wszystkich konwersji liczby całkowitej i zaokrąglenia. Zobacz [skrzypce, które zrobiłem z twojego] (http://jsfiddle.net/f8F7q/). – Pointy

1

Jeśli spojrzeć na sposób linie są blisko, a potem daleko od siebie w regularny wzór (pięć bliskich obszarach, w swoim przykładzie), który daje dobre wskazanie, że jest to związane z twoich funkcji trygonometrycznych. Niemal widać sinusoidę we wzorze.

W każdym razie twoja matematyka do rysowania promieni ma pewne błędy. Spróbuj to uproszczony przykład:

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 barThickness = 2; 

    context.lineWidth = barThickness; 
    context.strokeStyle = circleBackground; 


    var innerRadius = 30; 
    var outerRadius = 80; 
    var center = { x:50, y:50 }; 
    var percentDone = 60; 
    var angleOfPercentDone = percentDone * 360/100; 

    //rotate everything -90 degrees 
    angleOfPercentDone -= 90; 
    for(var angle = -90; angle < angleOfPercentDone; angle +=5) 
    { 
     //convert to radians 
     var rad = angle * Math.PI/180; 
     var c = Math.cos(rad); 
     var s = Math.sin(rad); 
     var innerPointX = center.x + (innerRadius * c); 
     var innerPointY = center.y + (innerRadius * s); 
     var outerPointX = center.x + (outerRadius * c); 
     var outerPointY = center.x + (outerRadius * s); 
     context.moveTo(innerPointX, innerPointY); 
     context.lineTo(outerPointX, outerPointY); 
     context.stroke(); 
    } 
} 

Zobacz skrzypce tutaj: http://jsfiddle.net/DXwrc/

Powiązane problemy