HTML5 Холст круговая диаграмма - PullRequest
22 голосов
/ 09 августа 2011

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

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>

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

Спасибо

Ответы [ 3 ]

35 голосов
/ 18 января 2013

Даже после поиска в 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" />
5 голосов
/ 14 января 2017

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

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

Рефакторинг также облегчает привязку значений к полям ввода, если это то, что вас интересует.

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

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

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

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

ctx.lineTo(center coordinates of circle);

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...