Представьте, что вы получили работу в ООО «Экономика для всех», и вашим первым заданием будет нарисовать круговую диаграмму удовлетворённости клиентов согласно результатам опроса.
Переменная result
содержит массив объектов, представляющих результаты.
var results = [
{name: "Удовлетворён", count: 1043, color: "lightblue"},
{name: "Нейтральное", count: 563, color: "lightgreen"},
{name: "Не удовлетворён", count: 510, color: "pink"},
{name: "Без комментариев", count: 175, color: "silver"}
];
Чтобы нарисовать диаграмму, мы рисуем несколько секторов, каждый из которых делается из арки и пары линий от центра. Угол мы вычисляем, деля полный круг (2π) на общее количество отзывов, и умножая на количество людей, выбравших данный вариант ответа.
var cx = document.querySelector("canvas").getContext("2d");
var total = results.reduce(function(sum, choice) {
return sum + choice.count;
}, 0);
// Start at the top
var currentAngle = -0.5 * Math.PI;
results.forEach(function(result) {
var sliceAngle = (result.count / total) * 2 * Math.PI;
cx.beginPath();
// center=100,100, radius=100
// from current angle, clockwise by slice's angle
cx.arc(100, 100, 100,
currentAngle, currentAngle + sliceAngle);
currentAngle += sliceAngle;
cx.lineTo(100, 100);
cx.fillStyle = result.color;
cx.fill();
});
Но диаграмма не расшифровывает значения секторов – это неудобно. Нам надо как-то нарисовать на холсте текст.
У контекста двумерного холста есть методы fillText
и strokeText
. Последний можно использовать для обведённых букв, но обычно используется fillText
. Он заполняет заданный текст цветом fillColor
.
var cx = document.querySelector("canvas").getContext("2d");
cx.font = "28px Georgia";
cx.fillStyle = "fuchsia";
cx.fillText("Я и текст могу рисовать!", 10, 50);
Можно задать размер, стиль и шрифт текста через свойство font
. В примере задаётся только размер и шрифт. Можно добавить наклон и жирность в начале строки.
Два последних аргумента fillText
(и strokeText
) задают позицию, с которой начинается текст. По умолчанию это начало линии, на которой «стоят» буквы – не считая свисающих частей букв типа р и у. Можно менять позицию по горизонтали, задавая свойству textAlign
значения "end"
или "center"
, а по вертикали – задавая textBaseline
"top"
, "middle"
, или "bottom"
.
В конце главы мы вернёмся к нашей диаграмме.
В компьютерной графике проводится различие между векторной и растровой графикой. Первая – то, чем мы занимались в этой главе, рисование при помощи логических описаний форм. Вторая – не задаёт формы, а работает на уровне пикселей.
Метод drawImage
позволяет выводить на холст пиксельные данные. Они могут быть взяты из элемента или с другого холста, которые не обязательно видны в самом документе. Следующий пример создаёт элемент и загружает в него файл изображения. Но он не может сразу начать рисовать при помощи этой картинки, потому что браузер мог не успеть её подгрузить. Для этого мы регистрируем обработчик события “load”
и рисуем после загрузки.
var cx = document.querySelector("canvas").getContext("2d");
var img = document.createElement("img");
img.src = "img/hat.png";
img.addEventListener("load", function() {
for (var x = 10; x < 200; x += 30)
cx.drawImage(img, x, 10);
});
По умолчанию drawImage
нарисует картинку оригинального размера. Ему можно задать два дополнительных параметра для изменения ширины и высоты.
Когда drawImage
задано девять аргументов, её можно использовать для рисования части изображения. Со второго по пятый аргументы обозначают прямоугольник (x, y, ширина и высота) в исходной картинке, который надо скопировать. С шестого по девятый – прямоугольник на холсте, куда его надо скопировать.
Это можно использовать, чтобы упаковывать несколько спрайтов (элементов картинки или кадров анимации) в один файл изображения, и рисовать только нужные его части. К примеру, есть у нас картинка игрового персонажа в разных позах: