2011-08-09 12 views
19

Ja próbuje utworzyć prosty wykres kołowy, jak pokazano na poniższym rysunku:HTML5 Canvas wykres kołowy

enter image description here

wykres pokaże wyników dla quiz, w którym użytkownik może wybrać albo, b lub c. Jest to 10 pytań, a użytkownik może wybrać tylko jedną opcję na pytanie.

Co chcę zrobić, to pokazać wykres kołowy z każdym segmentem będącym procentem 100% przez podanie wartości dla a, b lub c.

mam następujące pory:

var greenOne = "#95B524"; 
 
var greenTwo = "#AFCC4C"; 
 
var greenThree = "#C1DD54"; 
 

 
function CreatePieChart() { 
 
    var chart = document.getElementById('piechart'); 
 
    var canvas = chart.getContext('2d'); 
 
    canvas.clearRect(0, 0, chart.width, chart.height); 
 

 
    var total = 100; 
 

 
    var a = 3; 
 
    var b = 4; 
 
    var c = 3; 
 

 
    for (var i = 0; i < 3; i++) { 
 
    canvas.fillStyle = "#95B524"; 
 
    canvas.beginPath(); 
 
    canvas.strokeStyle = "#fff"; 
 
    canvas.lineWidth = 3; 
 
    canvas.arc(100, 100, 100, 0, Math.PI * 2, true); 
 
    canvas.closePath(); 
 
    canvas.stroke(); 
 
    canvas.fill(); 
 
    } 
 
} 
 
CreatePieChart();
<canvas id="piechart" width="200" height="200"></canvas>

Kolory są specyficzne dla wielkości segmentu, tak zielona służy do największych i zielone trzy w najmniejszym.

Dzięki

+0

Trochę więcej wysiłku może przejść długą drogę. Jaki jest twój problem? – TJHeuvel

+2

Nie jestem pewien, od czego zacząć od danych i rysowania wykresu – Cameron

Odpowiedz

28

Nawet po wyszukaniu Google i potrójne sprawdzanie moje radians wartości, itd. Byłem nadal kłopoty z tym, więc stworzyliśmy jsFiddle dla ludzi do zabawy jak żywy przykład i będzie również umieść poniższy kod.

var canvas = document.getElementById("can"); 
 
var ctx = canvas.getContext("2d"); 
 
var lastend = 0; 
 
var data = [200, 60, 15]; // If you add more data values make sure you add more colors 
 
var myTotal = 0; // Automatically calculated so don't touch 
 
var myColor = ['red', 'green', 'blue']; // Colors of each slice 
 

 
for (var e = 0; e < data.length; e++) { 
 
    myTotal += data[e]; 
 
} 
 

 
for (var i = 0; i < data.length; i++) { 
 
    ctx.fillStyle = myColor[i]; 
 
    ctx.beginPath(); 
 
    ctx.moveTo(canvas.width/2, canvas.height/2); 
 
    // Arc Parameters: x, y, radius, startingAngle (radians), endingAngle (radians), antiClockwise (boolean) 
 
    ctx.arc(canvas.width/2, canvas.height/2, canvas.height/2, lastend, lastend + (Math.PI * 2 * (data[i]/myTotal)), false); 
 
    ctx.lineTo(canvas.width/2, canvas.height/2); 
 
    ctx.fill(); 
 
    lastend += Math.PI * 2 * (data[i]/myTotal); 
 
}
<canvas id="can" width="200" height="200" />

+1

Podoba mi się to, jest super proste, bardzo lekkie, nie wymaga żadnych zewnętrznych skryptów takich jak jQuery, itp. Jest to dobre dla mnie, ponieważ planuję użyć setki tych załadowanych za pomocą częściowego żądania lol – RedactedProfile

+0

To jest świetne! Czy mogę dodać, że jeśli chcesz, aby segmenty zaczynały się od północy, zainicjuj 'var lastend = -1.57'. 1,57 to jedna czwarta liczby radianów w okręgu. Dzięki. –

3

Lubię poprzednią odpowiedź, ale czułem, że brakowało w kodzie jasności i tak naprawdę nie pokrywają, jak wykorzystać etykiety.

Przesunąłem wartości do macierzy obiektów danych dla łatwej deklaracji. Inne wartości, takie jak wartość procentowa, jawnie zadeklarowałem jako właściwość obiektu danych lub jako oddzielną zmienną. To, jak sądzę, ułatwia czytanie.

refaktoring wykonane również łatwiej związać wartości do pól wejściowych, czy to coś jesteś zainteresowany

Aby zobaczyć, co mam na myśli i grać z wartościami sprawdzić ten CodePen. http://codepen.io/zfrisch/pen/pRbZeb

var data = [{ 
 
    label: "one", 
 
    value: 100, 
 
    color: 'white' 
 
    }, { 
 
    label: "two", 
 
    value: 100, 
 
    color: 'skyBlue' 
 
    }, { 
 
    label: "three", 
 
    value: 100, 
 
    color: 'yellow' 
 
    }]; 
 

 
    var total = 0; 
 
    for (obj of data) { 
 
    total += obj.value; 
 
    } 
 

 
    var canvas = document.getElementById('myCanvas'); 
 
    var ctx = canvas.getContext('2d'); 
 
    var previousRadian; 
 
    var middle = { 
 
    x: canvas.width/2, 
 
    y: canvas.height/2, 
 
    radius: canvas.height/2, 
 
    }; 
 
    
 
    //background 
 
    ctx.beginPath(); 
 
    ctx.arc(middle.x, middle.y, middle.radius, 0, 2 * Math.PI); 
 
    ctx.closePath(); 
 
    ctx.stroke(); 
 
    ctx.fillStyle = "black"; 
 
    ctx.fill(); 
 
    //end of background 
 

 
    for (obj of data) { 
 
    previousRadian = previousRadian || 0; 
 
    obj.percentage = parseInt((obj.value/total) * 100) 
 
    
 
    ctx.beginPath(); 
 
    ctx.fillStyle = obj.color; 
 
    obj.radian = (Math.PI * 2) * (obj.value/total); 
 
    ctx.moveTo(middle.x, middle.y); 
 
    //middle.radius - 2 is to add border between the background and the pie chart 
 
    ctx.arc(middle.x, middle.y, middle.radius - 2, previousRadian, previousRadian + obj.radian, false); 
 
    ctx.closePath(); 
 
    ctx.fill(); 
 
    ctx.save(); 
 
    ctx.translate(middle.x, middle.y); 
 
    ctx.fillStyle = "black"; 
 
    ctx.font = middle.radius/10 + "px Arial"; 
 
    ctx.rotate(previousRadian + obj.radian); 
 
    var labelText = "'" + obj.label + "' " + obj.percentage + "%"; 
 
    ctx.fillText(labelText, ctx.measureText(labelText).width/2, 0); 
 
    ctx.restore(); 
 

 
    previousRadian += obj.radian; 
 
    }
<canvas id="myCanvas" width="500" height="500" ></canvas>

0

miałem ten sam problem przed, ale udało mi się rozwiązać ten problem później.

To, czego mi brakowało, to rysowanie łuku w kontekście i próbowałem go wypełnić, dzięki czemu kolor rozprzestrzeniał się po całym okręgu, ponieważ teraz kontekst był ograniczony tylko między linią promienia od środka do początku punkt łuku i łuk, aby związać kontekst.

Ale nie było innego granica linia od końca łuku do środka, jak tylko wyciągnąć tę linię za pomocą następujących czynności:

ctx.lineTo(center coordinates of circle); 

Mam pełną granicę ciasto, więc teraz jeśli wypełnię kolor w kontekście, nie rozprzestrzeni się w całym kręgu, ale będzie ograniczony do tego ciasta.