Flot — рисуем графики в jQuery
18 августа 2010
Flot — это JavaScript библиотека, предназначенная для рисования графиков. С ее помощью можно легко и быстро создавать красивые динамические графики, которые будут корректно работать в любом браузере независимо от того, какая ОС установлена у пользователя.
Примечание: все примеры, библиотека Flot, а также кое-какие дополнительные материалы к этой заметке собраны в этом архиве.
1. Простой график
Давайте нарисуем с помощью Flot какой-нибудь несложный график. Чтобы было чуточку интересней, пусть графиков будет сразу несколько. Для передачи данных библиотеке Flot, их нужно представить в следующем виде:
{ label: "Данные 1", color: 0, data: [[1, 0], [2, 10], [3, 70]]},
{ label: "Данные 2", color: 1, data: [[1, 130], [2, 230], [3, 320]]}
// ВАЖНО: IE не понимает запятых на конце :(
];
Числа 1, 2 и 3 — это координаты точек по оси абсцисс, числа рядом с ними — координаты по оси ординат. Указывать названия рядов и используемые цвета не обязательно. Будьте внимательны — если поставить запятую вслед за последним элементом массива или хэша, Internet Explorer скажет, что в коде ошибка, и откажется его выполнять. Все остальные браузеры обрабатывают эту ситуацию нормально, что в очередной раз доказывает, что создателям IE нужно оторвать руки.
Если мы хотим, чтобы по оси OX отображались даты и время, их значения должно быть представлено в UTC (имеются в виду числа типа 1149537600000). Мне кажется не очень удобным работать с UTC, тем более, что избежать этого можно с помощью незамысловатого приема:
{ label: "Данные 1", color: 0,
data: [["2010/10/01", 0], ["2010/11/01", 1], ["2010/12/01", 7]]},
{ label: "Данные 2", color: 1,
data: [["2010/10/01", 13], ["2010/11/01", 23], ["2010/12/01", 32]]}
];
// преобразуем даты в UTC
for(var j = 0; j < all_data.length; ++j) {
for(var i = 0; i < all_data[j].data.length; ++i)
all_data[j].data[i][0] = Date.parse(all_data[j].data[i][0]);
}
Можно считать, что все уже написано — до готового графика осталось совсем чуть-чуть:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Название страницы</title>
<!-- подгружаем Flot -->
<!--[if IE]><script language="javascript" type="text/javascript" src="flot/excanvas.min.js"></script><![endif]-->
<script language="javascript" type="text/javascript" src="flot/jquery.js"></script>
<script language="javascript" type="text/javascript" src="flot/jquery.flot.js"></script>
</head>
<body>
<p><noscript><strong style="color: red;">
Для отображения данных необходимо включить JavaScript!
</strong></noscript></p>
<!-- тут будет выводится график -->
<div id="placeholder" style="width:600px;height:300px;"></div>
<script language="javascript" type="text/javascript">
// данные для графиков
var all_data = [
{ data: [["2010/10/01", 0], ["2010/10/5", 1],
["2010/10/10", 7], ["2010/10/15", 8]]},
{ data: [["2010/10/01", 13], ["2010/10/5", 23],
["2010/10/10", 32], ["2010/10/15", 33]]}
];
// преобразуем даты в UTC
for(var j = 0; j < all_data.length; ++j) {
for(var i = 0; i < all_data[j].data.length; ++i)
all_data[j].data[i][0] = Date.parse(all_data[j].data[i][0]);
}
// свойства графика
var plot_conf = {
series: {
lines: {
show: true,
lineWidth: 2
}
},
xaxis: {
mode: "time",
timeformat: "%y/%m/%d",
}
};
// выводим график
$.plot($("#placeholder"), all_data, plot_conf);
</script>
</body>
</html>
На мой взгляд, все предельно просто и в комментариях не нуждается. Результат выглядит следующим образом:
2. Выводим легенду
Вывести легенду к графику очень просто — достаточно указать label в описании данных, как мы это делали в начале статьи. Как вы могли заметить, в последнем примере ассоциативный массив содержал только элементы data.
По умолчанию легенда отображается в правом верхнем углу графика, частично закрывая его. Чтобы легенда отобразилась в конкретном месте на странице, достаточно дописать в переменную plot_conf:
container: $("#legend")
} // помним про запятые и IE
… где legend — это id слоя, в котором будет выведена легенда. Полный код примера вы можете посмотреть в файле step2.html, который находится в прилагающемся к статье архиву.
3. Скрываем данные
С помощью Flot можно сделать одну очень удобную штуку — добавить в легенду чекбоксы, кликая по которым, пользователь сможет скрывать ряды данных. К сожалению, в Flot нет метода типа СкрытьРяд(), потому при каждом клике график придется полностью перерисовывать. А давайте-ка в честь этого напишем функцию, отвечающую за перерисовку!
redraw();
function redraw() {
var data = [];
for(var j = 0; j < all_data.length; ++j)
if(!hide[j]) // что скрываем, а что нет
data.push(all_data[j]);
$.plot($("#placeholder"), data, plot_conf);
// легенду рисуем только один раз
plot_conf.legend.show = false;
}
Массив hide содержит all_data.length элементов. Если i-ый элемент массива равен true, значит i-ый ряд данных нужно скрыть. После первого рисования графика следует присвоить plot_conf.legend.show значение false. Легенду достаточно нарисовать один раз, незачем тратить на ее повторное создание лишние такты процессора.
После того, как Flot нарисует легенду, мы можем добавить в нее чекбоксы:
// еще IE не умеет заменять innerHTML в table
var legend = document.getElementById('legend');
var legend_tbl = legend.getElementsByTagName('table')[0];
var legend_html = '<table style="font-size: smaller;' +
' color: rgb(84, 84, 84);"><tbody>';
for(var i = 0; i < legend_tbl.rows.length; i++) {
legend_html += '<tr>' +
'<td><input type="checkbox" onclick="hide['+ i +']=!hide['+ i
+ '];redraw();" checked="1"></td>'
+ legend_tbl.rows[i].innerHTML
+ '</tr>';
}
legend_html += "</tbody></table>";
legend.innerHTML = legend_html;
Internet Explorer не умеет изменять innerHTML таблиц, в связи с чем приходится переписывать таблицу с нуля и присваивать полученный код innerHTML слою, эту таблицу содержащему. Интересное объяснение того, почему IE так себя ведет, вы найдете на ХабраХабре. Правда, на момент написания этих строк, статья была недоступна:
Доступ к публикации закрыт
Вы пытаетесь открыть публикацию, написанную пользователем GreLI.
Автор переместил топик в черновики.
На всякий случай я взял копию статьи из кэша Google и сохранил в архиве, прилагающемуся к статье.
При использовании приема с чекбоксами важно не забыть жестко прописать соответствие нашим данным конкретных цветов, иначе при перерисовке графика ряды будут менять свой цвет. В результате описанных в этом разделе действий мы получим что-то вроде этого:
Полный код примера вы найдете в файле step3.html.
4. Кроме того
Возможности Flot настолько велики, что для полного их описания потребовалась бы далеко не одна и не две таких статьи. За кадром осталась поддержка плагинов, подгрузка данных с помощью Ajax и многое другое. Чтобы составить более-менее полное впечатление о возможностях библиотеки, загляните в раздел с примерами на сайте проекта.
Напоследок я приведу еще один пример, работу которого я хотел бы оставить для самостоятельного изучения.
Нажимая по ссылке «Сменить вид», пользователь может выбирать, в каком виде будут отображаться данные — в виде гистограмм или графиков. Превью внизу страницы позволяет выбрать отображаемый диапазон данных. Полный код примера вы найдете в прилагающемся к статье архиву, в файле result.html.
5. Заключение
Flot — это прекрасная библиотека, которая должна быть в арсенале каждого веб-разработчика. Открытый код, полная кроссплатформенность, мощный функционал, отличная документация — о чем еще можно мечтать? В очередной раз я убеждаюсь в том, что этот ваш Flash никому не нужен!
Дополнение: Если у вас возникли проблемы с работой Flot в Internet Explorer 9, загляните сюда.
Метки: JavaScript.
Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.