Долгое время в своих проектах использовал Flash-графики, вместо обычных картинок. Они и красивее и более функциональны, да и серверу не нужно напрягаться для генерации картинок. Но в связи с тем, что некоторые фирмы не очень дружат с Flash, пришлось поискать замену без использования Flash.До этого использовал AmCharts, первым делом глянул на их сайт, они уже выпустили JS версию своих графиков, но как-то не понравилось, по ощущениям — сыровато еще. После недолгого гугления был найден Highstock, от авторов Highcharts JS. Отличается в первую очередь возможностью выводить графики, привязанные к времени, с большим количеством точек, масштабированием, удобной навигацией. Да и чисто внешне понравился больше AmCharts.
Сбор данных
Для тренировки, чтобы было не сильно скучно, решил сделать простенькую страницу с мониторингом результатов народного голосования Премии Рунета. Так можно и с графиком попрактиковаться, да и посмотреть, будет ли аномальное поведение на голосовании (обычно говорящее о накрутках).
Подготовку особо расписывать не буду, в общих чертах. Так как к самой премии не имею никакого отношения, поэтому просто написал PHP-скрипт, который, скачивает главную страницу, парсит её регулярками, после чего количество голосов и позиции заносит в базу. Скрипт повешен на крон и выполняется каждые 5 минут.
Подготовка данных
Итак, данные есть, теперь нужно подумать, как их выводить. Поскольку сайтов принимающих участие в голосовании 50 штук, плюс разрывы между сайтами составляют 2 порядка, то выводить все сайты вместе не имеет смысла. Немного пораскинув мозгами, остановился на следующих вариантах вывода:
- По умолчанию, выводятся первые 3 позиции.
- Диапазоны по 10 позиций (1-10,11-20 и т.п.).
- Выбор конкретных сайтов (1,3,10).
- Если выбран только один сайт, то показываются также его ближайшие конкуренты, один на позицию выше, другой на позицию ниже.
- Простой массив со значениями для оси Y, в таких случаях значения по X рассчитываются автоматически в соответствии с указанными правилами.
data: [0, 5, 3, 5] - Массив, содержащий значения X,Y.
data: [[5, 2], [6, 3], [8, 2]] - Массив объектов — самый продвинутый вариант, позволяющий хоть каждую точку настраивать.
data: [{ name: 'Точка 1', color: '#00FF00', y: 0 }, { name: 'Точка 2', color: '#FF00FF', y: 5 }]
Также поскольку нужно выводить несколько графиков, решил избавиться от дублирования времени. В итоге PHP-скрипт генерит данные в формате JSON:
data: [ [1, id1val, id2val,…,idNval], // Первая точка [2, id1val, id2val,…,idNval], // Вторая точка … ]
Где первое значение означает время (timestamp делится на 300 сек. и отнимается стартовое время). Для преобразования да��ных в отдельные массивы для каждого графика, напишем функцию
// Преобразуем в отдельные массивы var c = info.data.length; // Количество графиков for(var i = 0, l = info.title.length; i < l; i++){ seriesOptions[i] = { name: info.title[i], // Название сайта data: [] // Пустой массив с данными }; for(var j = 0; j < c; j++){ // Добавляем пары timestamp в миллисекундах и количество голосов seriesOptions[i].data.push([(info.data[j][0] + 4404683) * 300000, info.data[j][i+1]]); } }
Настраиваем внешний вид графика
Для начала переведем выводящиеся надписи на русский, изменим разделитель тысяч, и сделаем, чтобы время выводилось не в UTC, а в локальном времени пользователя.
Highcharts.setOptions({ lang: { rangeSelectorZoom: 'Маcштаб', rangeSelectorFrom: 'От', rangeSelectorTo: 'До', thousandsSep: ' ' }, global: { useUTC: false } });
Далее настраиваем внешний вид с помощь объекта опций. Сначала общие опции.
chart: { renderTo: 'chart', // DIV контейнер в который будет встраиваться график zoomType: 'x', // разрешаем зумировать по оси X backgroundColor: '#f9f9f9' // Сделаем слегка серый фон }
Настройка кнопок выбора временных интервалов.
rangeSelector: { buttons: [{ // Настраиваем свои кнопки для временных интервалов type: 'hour', // Тип интервала: 'millisecond', 'second', 'minute', 'day', 'week', 'month', 'ytd' (текущий год), 'year' and 'all' count: 3, // Количество единиц указанных в type text: '3 часа' }, { type: 'all', text: 'всё' }], inputDateFormat: '%d.%m.%Y', // Меняем на привычный для нас формат даты в интервалах inputEditDateFormat: '%d.%m.%Y', buttonTheme: { width: 60 // Увеличим ширину кнопки }, selected: 2 // Какая кнопка выбрана по умолчанию }
Теперь займемся всплывающей подсказкой (выводится при наведении на график)
tooltip: { backgroundColor: 'rgba(250, 250, 250, .85)', // Фон немного темнее borderColor: 'rgba(100, 100, 100, .90)', // Цвет границы (по умолчанию меняется автоматом) xDateFormat: '%d.%m.%Y %H:%M', // Наш формат даты // Тут немного увеличиваем размер даты headerFormat: '<span style="font-size: 12px">{point.key}</span><br/>', // Формат надписей в подсказке, названия цветом графика, а значения жирным pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b><br/>' }
Включаем и настраиваем легенду (по умолчанию она выключена). Вывел наверх, так как вывод
под графиком пока работает коряво (накладывается на шкалу времени), как и вывод сбоку (не правильно обрезаются длинные названия)
legend: { enabled: true, align: 'center', itemWidth:234, // указал ширину, чтобы выводились сайты в 4 колонки verticalAlign: 'top' }
Результат
После того как всё собрали в кучу, добавляем для удобства кнопки выбора сайтов. И наблюдаем за «битвой титанов».
Вот так это выглядит:

В ближайшее время хочу еще прикрутить автообновление, чтобы каждые 5 минут скачивались только новые точки и добавлялись в график. Но глюков в библиотечке пока довольно много, при не очень стандартных действиях.
И напоследок несколько ссылок:
Официальный сайт Highcharts и Highstock
Дока по Highstock API
Официальный сайт amСharts
