HTML5 холст круговая диаграмма
Я пытаюсь создать простую круговую диаграмму, как показано на рисунке ниже:
![enter image description here]()
На диаграмме будут показаны результаты для викторины, где пользователь может выбрать a, 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>
Ответы
Ответ 1
Даже после поиска 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" />
Ответ 2
Мне нравится предыдущий ответ, но я чувствовал, что ему не хватает четкости кода, и на самом деле он не охватывал способы использования меток.
Я переместил значения в массив объектов данных для легкого объявления. Другие значения, такие как процент, я явно объявлен как свойство для объекта данных или как отдельная переменная. Это, я думаю, облегчает чтение.
Рефакторинг также упростил привязку значений к полям ввода, если это то, что вас интересует.
Чтобы узнать, что я имею в виду и играю со значениями, проверьте этот код: 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>
Ответ 3
У меня была такая же проблема, но я смог решить эту проблему позже.
То, что мне не хватало, я рисовал арку в контексте и пытался ее заполнить, из-за чего цвет распространялся по всему кругу, потому что теперь контекст был связан только между радиусом от центра до начальной точки арки и арки, чтобы связать контекст.
Но не было другой границы линии от конца дуги до центра, как только я рисую эту строку, используя следующее:
ctx.lineTo(center coordinates of circle);
У меня есть полная граница пирога, поэтому теперь, если я заполню цвет в контексте, он не будет распространяться внутри всего круга, но будет ограничен этим пирогом.