Динамические графики на JQuery + Flot

3rd Июнь 2011 | Категории: JavaScript | Метки: , , ,

Для создания графиков на web-страницах обычно используется один из трех вариантов:

  • Генерация картинки на стороне сервера (perl, php, java…)
  • Генерация картинки прямо в браузере, используя flash-объект.
  • Генерация картинки прямо в браузере, используя javascript.

О последнем способе мы и поговорим. Самой популярной js библиотекой на данный момент является jquery. Для jquery есть множество библиотек для визуализации данных, но одна из самых лучших — flot. Flot кроссбраузерная библиотека, позволяющая отрисовывать график на канве (canvas). Причем график можно изменять непосредственно на загруженной странице, без перезагрузки и дополнительных запросов к серверу. Но обо всем по порядку.

Для начала скачаем библиотеку Flot (в конце статьи можно найти все ссылки) . За основу для своих экспериментов возьмем второй пример — Different graph types и удалим все линии кроме d1 и d3. Помимо этого, добавим 2 поля для ввода данных и одну кнопку, по нажатию которой график будет перерисовываться:

$("#redraw").click(function (e) {
	e.preventDefault();
	re_plot();
});

Здесь мы отменяем событие по умолчанию, и вызываем свою функцию:

function re_plot() {
	var x = parseInt($("#x").val());
	var y = parseInt($("#y").val());
 
	var d1 = [];
	var d3 = [];
	for (var i = -7; i < 7; i += 0.5)
	{
		d1.push([i, x * Math.sin(i)]);
		d3.push([y + i, Math.cos(i)]);
	}
 
	$.plot($("#placeholder"), [
		{
			data: d1,
			lines: { show: true, fill: true }
		},
		{
			data: d3,
			points: { show: true }
		}
	]);
	return false;
}

Функция перерисовки графика очень проста: получаем значение полей для ввода и заполняем массивы новыми значениями. После чего, вызываем встроенную функцию библиотеки flot для отрисовки данных.

Пример 1: JQuery + Flot

Изменяя значения X и Y и нажимая кнопку reDRAW, мы будем изменять график. Каждый раз нажимать кнопку не хочется… Нужна динамика… Поэтому добавим два слайдера, перемещая ползунки которых, мы будем автоматически изменять график.

Для того чтобы на странице появился слайдер, нужно подключить библиотеку jquery UI, определить div, в котором будет слайдер:

x: <input id="x" type="text" value="1" readonly="readonly"> <div id="xslider"></div>

И задать начальную инициализацию в js:

	$("#xslider").slider({
	range: "min",
	value: 1,
	min: 1,
	max: 10,
	step: 1,
	slide: function (a, b) {
		$("#x").val(b.value);
		re_plot();
	}
});

Указанные параметры сделают слайдер с диапазоном от 1 до 10 и шагом ползунка равным 1 (параметры min, max, step). При перетаскивании — будет произведено закрашивание слева на право (range: «min») и вызвана анонимная функция (определённая в параметре slide). Эта функция изменит значение input c id = x на текущее значение слайдера. И вызовет уже знакомую нам функцию перерисовки графика. Аналогично инициализируется и второй слайдер.

Пример 2: JQuery + Flot

Пример слишком простой и далек от реальных задач. Поэтому, изучив документацию и формулы, создадим ипотечный график-калькулятор. Большинство кредитов делятся по типу выплат на аннуитеты (погашение кредитов происходит равными суммами, но вначале большую часть этой суммы составляет обслуживание процентов кредита) и на дифференцированные платежи (выплаты по кредиту осуществляют равными долями, а процентные платежи меняются от максимума в начале, до минимума — в конце). Более подробно с теорией можно ознакомиться по ссылкам в конце статьи.

Нам необходимо три слайдера:

  • Стоимость жилья и первоначальный взнос (двойной слайдер);
  • Срок кредита;
  • Процентная ставка;

Также добавим нужное число текстовых полей для отображения расчетной информации. В функции re_plot() будем проводить перерасчет всех параметров и выводить 2 графика. Точки на графиках сделаем активными: при наведении указателя мыши будем показывать номер месяца и сумму платежа. Для того чтобы это сделать, необходимо:

  • В опциях графика добавить:
    grid: { hoverable: true, clickable: true }
  • Определим функцию showTooltip, которая будет рисовать всплывающий div с данными.
  • Назначить событие на DIV c графиком:
    $("#placeholder").bind("plothover", function());

Пример 3: JQuery + Flot. Ипотечный калькулятор

PS. Полезные материалы:

Библиотеки и примеры их использования:

Немного теории:

Subscribe without commenting


  1. андрей
    5th Октябрь 2011 в 04:39

    У меня по оси х выводится одинаковые значения. Выглядит так » Oct 1 Oct 2 Oct 2 Oct 3 Oct 3 Oct 4 Oct 4 Oct 4″, это даты.
    как убрать дубли?

  2. Тарлюн Максим
    5th Октябрь 2011 в 08:22

    @андрей
    в настройках добавьте minTickSize, примерно так:

    xaxis: {
    mode: «time»,
    minTickSize: [1, «day»],
    }

  3. pupok
    27th Май 2013 в 17:38

    Добрый день! Подскажите пожалуйста как правильно передать дату, что бы отображалась правильно(год-мес-число) ,а то у меня выводит только время.. заранее спасибо.

  4. Тарлюн Максим
    28th Май 2013 в 08:35

    Если вы используете стандартную шкалу с типом «time» — то при увеличении масштаба будут автоматически появляется даты. Но если вам нужно самому регулировать формат даты, то нужно настроить параметр xaxis:

    Параметр "timeformat" задает строки даты на графике. Задать можно, например, так:

    xaxis: {
    mode: "time",
    timeformat: "%y/%m/%d"
    }

    В результате будет метка будет подписана так: "2000/12/24". Поддерживаются следующие параметры для задания формата даты

    %h': часы
    %H': часы (дополняются нулем впереди)
    %M': минуты (дополняются нулем впереди)
    %S': секунды (дополняются нулем впереди)
    %d': день месяца (1-31)
    %m': месяц (1-12)
    %y': год (4 цифры)
    %b': название месяца (изменяемое)

    Названия месяцов можно менять, задав параметр "monthNames". Для России это будет выглядеть так:

    monthNames: ["янв", "фев", "мар", "апр", "май", "июн", "июл", "авг", "сен", "окт", "ноя", "дек"]

    Следует отметить, что временные параметры "tickSize" и "minTickSize" немного особенные тем, что это массивы формата "[value, unit]", где unit принимает значения "second", "minute", "hour", "day", "month" и "year". Пример ниже:

    minTickSize: [1, "month"]

    код задает интервал между метками не менее месяца.
    Если задать для axis.tickSize значени [2, "day"], то интервал между метками будет составлять два дня.

  5. pupok
    3rd Июнь 2013 в 14:08

    Спасибо большое помогло только не могу еще понять как правильно передать данные из базы. В запросе я задаю к примеру с 2013-01-01 по 20102-01 запрос уходит в базу отбирает совпадения вданный период и должен отрисовать на графике по соответствующим совпадениям в базе, а мне возвращает 16-01-1970 (( прошу прощения за такой вопрос. Поймите пожалуйста новичка. )) Заранее очень благодарен.

  6. Тарлюн Максим
    4th Июнь 2013 в 09:02

    В качестве метки времени необходимо использовать timestamp с микросекундами. Поставить точку с текущей датой:
    [1370318382000, 'value']

  7. pupok
    4th Июнь 2013 в 12:39

    Спасибо большое заработало. А вы не могли б подсказать еще одну штуку. Я сделал график точки отображаются и подсвечиваются. Как сделать чтобпри нажатии на точку на графике выполнялась передача данных, которые хранятся в этой дате, в таблицу под графиком. А при нажатии например на следующую происходило обновление данных в таблице. С Уважением. Ответьте пожалуйста даже если не знаете как это сделать)))

  8. Тарлюн Максим
    4th Июнь 2013 в 13:04

    @pupok
    Ничего подобного не делал.
    Советую посмотреть официальную документацию: http://flot.googlecode.com/svn/trunk/API.txt, и поискать по слову «click».

    Вы подкинули хорошую идею для очередной статьи.

  9. pupok
    4th Июнь 2013 в 13:08

    Я был бы очень рад чтоб она как можно раньше появилась )) спасибо попробую .

  10. pupok
    21st Сентябрь 2013 в 16:54

    добрый день. подскажите пожалуйста как убрать наползание дат по оси Х, чтоб при масштабировании мышкой дата изменялась в соответствии с масштабом (год – по месяцам, месяц по дням, день часы и минуты и т.д.) что бы не наползали друг на друга.
    у меня настройки такие:
    var plot_conf = {
    series:{
    points:{radius: 3,show: true},
    lines:{show: true,fill: false},
    shadowSize: 0 },
    grid:{hoverable: true,
    clickable: true,
    markings: weekendAreas },
    xaxis:{zoomRange: «time»,
    panRange: «time»,
    mode: «time»,
    timeformat: » %d/%m/%y %H %M %S»,
    minTickSize:[1,»second»],
    monthNames:[«янв»,»фев»,»мар»,»апр»,»май»,»июн»,
    «июл»,»авг»,»сен»,»окт»,»ноя»,»дек»] },
    zoom:{interactive: true},
    pan:{interactive: true} };
    С Уважением.

  11. pupok
    21st Сентябрь 2013 в 17:02

    и если можете подскажите еще такой вопрос не знаете ли Вы как сделать правильно отображение не графике я запрашиваю из базы данные (дата время) и мне их нужно разнести во времени например (21.09.13 00:00:01 и 21.09.13 10:00:01 т.е. при масштабировании я должен видеть две точки по Х с амплитудой У = 1 и 1, а у меня получается что по Х две точки но на одной вертикальной прямой в одно время, а У = 1 и 2 и нет горизонтального разноса в одном дне..) С Уважением.

  12. Герман
    2nd Март 2015 в 00:27

    @Тарлюн Максим
    monthName -> monthNames
    сначала не мог понять почему не работает 🙂

  13. Тарлюн Максим
    2nd Март 2015 в 00:37

    @Герман
    исправил