2011-08-09 3 views
19

Я пытаюсь создать простую круговую диаграмму, как показано на рисунке ниже:HTML5 Canvas круговая диаграмма

enter image description here

График покажет результаты для викторины, где пользователь может выбрать либо, b или c. Это 10 вопросов, и пользователь может выбрать только один вариант для каждого вопроса.

Что я хочу сделать, это показать круговую диаграмму, в которой каждый сегмент будет составлять процент от 100%, передавая значения для a, b или c.

У меня есть следующие до сих пор:

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>

Цвета являются специфическими для размера сегмента, поэтому используется зеленый один для самой большой и зеленый три для самых маленьких.

Благодаря

+0

Немного больше усилий может пройти долгий путь. В чем проблема? – TJHeuvel

+2

Я не уверен, с чего начать с данных и рисования диаграммы – Cameron

ответ

28

Даже после поиска Google и тройной проверка моих радианов значения и т.д. Я был еще возникли проблемы с этим, так что я создал jsFiddle для людей, чтобы играть с в качестве живого примера и буду отправьте код ниже.

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

Мне это нравится, это очень просто, очень легко, не требует каких-либо внешних скриптов, таких как jQuery и т. Д. Это хорошо для меня, потому что я планирую использовать сотни из них загружены через частичный запрос lol – RedactedProfile

+0

Это замечательно! Могу ли я добавить, что если вы хотите, чтобы сегменты начинались с полуночной позиции, инициализируйте 'var lastend = -1.57'. 1.57 - четверть числа радианов в круге. Благодарю. –

3

Мне нравится предыдущий ответ, но я чувствовал, что не хватает ясности кода, и это на самом деле не охватывают, как использовать метки.

Я переместил значения в массив объектов данных для легкого объявления. Другие значения, такие как процент, я явно объявлен как свойство для объекта данных или как отдельная переменная. Это, я думаю, облегчает чтение.

Рефакторинг также стало проще связать значения поля ввода, если это то, что вы заинтересованы в

Чтобы увидеть, что я имею в виду и играть со значениями проверить это 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

у меня была такая же проблема раньше, но я был в состоянии решить эту проблему позже.

Что мне не хватало, я рисовал арку в контексте и пытался ее заполнить, из-за чего цвет распространялся по всему кругу, потому что теперь контекст был связан только между линией радиуса от центра до начала точку арки и арку, чтобы связать контекст.

Но не было никакой другой граничной линии от конца дуги к центру, как только я рисую эту строку, используя следующее:

ctx.lineTo(center coordinates of circle); 

У меня есть полный границы пирога, так что теперь если я заполню цвет в контексте, он не будет распространяться внутри всего круга, но будет ограничен этим пирогом.

Смежные вопросы