Круг, дуга и круговой граф с Canvas и JavaScript
Алгоритм рисования пирогового графа с надписями, оператор HTML 5 и немного тригонометрии...
Для рисования простого круга используется метод Канваса с длиной 2 * PI.
<script>
function circle()
{
var canvas = document.getElementById("canvas1");
var context = canvas.getContext("2d");
context.beginPath();
context.lineWidth="2";
context.arc(100, 100, 90, 0, 2 * Math.PI);
context.stroke();
}
circle();
</script>
Размер каневы - 200 х 200 пикселей. Центр круга в x = 100, y = 100 дается аргументами x и y функции дуги.
Радиус 90 пикселей является третьим аргументом. Третий и четвертый аргументы дают стартовый угол, 0 и окончательный угол, дважды PI.
Можно игнорировать аргумент о том, что смысл вращения здесь лишний.
Круг может быть заполнен методом fill
Для заполнения круга к предыдущему коду добавляется команда fill, но для определения цвета также присваивается атрибут fillStyle.
Элемент «Удар» может быть сохранен для добавления границы или пропущен только для цветного круга.
Так же, как был создан метод fillRect для рисования полного прямоугольника, определяется функция fillCircle для получения полного круга.
function fillCircle()
{
var canvas = document.getElementById("canvas2");
var context = canvas.getContext("2d");
context.beginPath();
context.fillStyle="#FF4422"
context.arc(80, 80, 70, 0, 2 * Math.PI);
context.fill();
}
fillCircle();
Создать пироговый график
Создается граф, состоящий из круговых секторов или «долей пирога», создавая эти сектора с помощью методов arc, lineTo и fill.
- Для совместного использования графика значения, которые должны быть назначены секторам, каждая дуга будет пропорциональна показанному статистическому значению и в процентах от числа PI * 2, которое является окружностью круга.
- Каждая часть пирога соответствует дуге, положение которой находится от конца предыдущего дуга, до новой позиции, соответствующей PI * 2 * значение/сумма.
Дуга прорисовывается с помощью функции дуги (в начале она не прорисовывается целиком). - Следует добавить поправку, чтобы первая часть была вверху, для чего следует сделать вывод PI/2, который соответствует четверти круга.
- Мы видим радиус из центра в последнее положение. Как и дуга, она на самом деле будет невидима на графике, потому что имеет тот же цвет, что и сектор.
На самом деле, поскольку только что нарисовали дугу, функция moveTo бесполезна, достаточно продолжить контур, идущий от окружности до центра круга методом lineTo. - Мы заполняем участок назначенного ему цвета методом филла. Последовательные цвета выбираются из предварительно определенного индексированного списка.
Пример :
Исходный код
function pie(ctx, w, h, datalist)
{
var radius = h / 2 - 5;
var centerx = w / 2;
var centery = h / 2;
var total = 0;
for(x=0; x < datalist.length; x++) { total += datalist[x]; };
var lastend=0;
var offset = Math.PI / 2;
for(x=0; x < datalist.length; x++)
{
var thispart = datalist[x];
ctx.beginPath();
ctx.fillStyle = colist[x];
ctx.moveTo(centerx,centery);
var arcsector = Math.PI * (2 * thispart / total);
ctx.arc(centerx, centery, radius, lastend - offset, lastend + arcsector - offset, false);
ctx.lineTo(centerx, centery);
ctx.fill();
ctx.closePath();
lastend += arcsector;
}
}
var datalist= new Array(35, 25, 20, 12, 7, 1);
var colist = new Array('blue', 'red', 'green', 'orange', 'gray', 'yellow');
var canvas = document.getElementById("canvas3");
var ctx = canvas.getContext('2d');
pie(ctx, canvas.width, canvas.height, datalist);
Значения находятся в таблице datalist, а цвета - в colist. Эти две таблицы отображаются в функции pie () для создания последовательных секторов в соответствии с последовательными значениями и цветами. Примечание: Не используйте функцию для (x в таблице), она не работает .
Можно сплющить график, чтобы создать эффект 3D, с функцией масштабирования, см. статью на эллипсе.
Код был протестирован со всеми браузерами, поддерживающими Canvas .
Надписи на круговом графике
Отображение обозначений рядом с графиком с соответствующими значениями не так значимо, как если бы они были размещены на графике.

Пример: Рыночные доли браузеров в мае 2015 года по версии StatCounter .
С небольшой тригонометрией эти формулировки можно расположить в центре каждой части графа. За исключением случаев, когда кварталы слишком малы, это становится нечитаемым, поэтому мы просто пропускаем слова.
Исходный код
function pie(ctx, w, h)
{
var radius = h * 2 - 5;
var centerx = w / 2;
var centery = h / 2;
var lastend = 0;
var offset = Math.PI / 2;
var labelxy = new Array();
var fontSize = Math.floor(canvas.height / 33);
ctx.textAlign = 'center';
ctx.font = fontSize + "px Arial";
var total = 0;
for(x=0; x < datalist.length; x++) { total += datalist[x]; };
for(x=0; x < datalist.length; x++)
{
var thispart = datalist[x];
ctx.beginPath();
ctx.fillStyle = colist[x];
ctx.moveTo(centerx,centery);
var arcsector = Math.PI * (2 * thispart / total);
ctx.arc(centerx, centery, radius, lastend - offset, lastend + arcsector - offset, false);
ctx.lineTo(centerx, centery);
ctx.fill();
ctx.closePath();
if(thispart > (total / 20))
labelxy.push(lastend + arcsector / 2 + Math.PI + offset);
lastend += arcsector;
}
var lradius = radius * 3 / 4;
ctx.strokeStyle = "rgb(0,0,0)";
ctx.fillStyle = "rgb(0,0,0)";
for(i=0; i < labelxy.length; i++)
{
var langle = labelxy[i];
var dx = centerx + lradius * Math.cos(langle);
var dy = centery + lradius * Math.sin(langle);
ctx.fillText(datalist[i], dx, dy);
}
}
On a ajouté le tableau labelxy pour stocker la position de chaque libellé qui est calculée lors du dessin du graphe. Le texte est placé après car il peut déborder d'un secteur.
Lorsque une portion du graphe - donc un pourcentage statistique - est inférieure à 1/20 ème de la distribution totale, le libellé n'est pas placé sur le graphe pour éviter un entassement de texte qui deviendrait illisible. En fait, si un graphe en tarte à de trop nombreux quartiers, alors les pourcentages seraient mieux représentés sur un graphe en barres. Un autre chapitre à ajouter à ce tutoriel...
Une démonstration de ces algorithmes est donnée par le générateur de graphe circulaire en ligne disponible sur ce site.