Долгое время в своих проектах использовал Flash-графики, вместо обычных картинок. Они и красивее и более функциональны, да и серверу не нужно напрягаться для генерации картинок. Но в связи с тем, что некоторые фирмы не очень дружат с Flash, пришлось поискать замену без использования Flash.
До этого использовал AmCharts, первым делом глянул на их сайт, они уже выпустили JS версию своих графиков, но как-то не понравилось, по ощущениям — сыровато еще. После недолгого гугления был найден Highstock, от авторов Highcharts JS. Отличается в первую очередь возможностью выводить графики, привязанные к времени, с большим количеством точек, масштабированием, удобной навигацией. Да и чисто внешне понравился больше AmCharts.
Для тренировки, чтобы было не сильно скучно, решил сделать простенькую страницу с мониторингом результатов народного голосования Премии Рунета. Так можно и с графиком попрактиковаться, да и посмотреть, будет ли аномальное поведение на голосовании (обычно говорящее о накрутках).
Подготовку особо расписывать не буду, в общих чертах. Так как к самой премии не имею никакого отношения, поэтому просто написал PHP-скрипт, который, скачивает главную страницу, парсит её регулярками, после чего количество голосов и позиции заносит в базу. Скрипт повешен на крон и выполняется каждые 5 минут.
Итак, данные есть, теперь нужно подумать, как их выводить. Поскольку сайтов принимающих участие в голосовании 50 штук, плюс разрывы между сайтами составляют 2 порядка, то выводить все сайты вместе не имеет смысла. Немного пораскинув мозгами, остановился на следующих вариантах вывода:
Также поскольку нужно выводить несколько графиков, решил избавиться от дублирования времени. В итоге PHP-скрипт генерит данные в формате JSON:
Где первое значение означает время (timestamp делится на 300 сек. и отнимается стартовое время). Для преобразования данных в отдельные массивы для каждого графика, напишем функцию
Для начала переведем выводящиеся надписи на русский, изменим разделитель тысяч, и сделаем, чтобы время выводилось не в UTC, а в локальном времени пользователя.
Далее настраиваем внешний вид с помощь объекта опций. Сначала общие опции.
Настройка кнопок выбора временных интервалов.
Теперь займемся всплывающей подсказкой (выводится при наведении на график)
Включаем и настраиваем легенду (по умолчанию она выключена). Вывел наверх, так как вывод
под графиком пока работает коряво (накладывается на шкалу времени), как и вывод сбоку (не правильно обрезаются длинные названия)
После того как всё собрали в кучу, добавляем для удобства кнопки выбора сайтов. И наблюдаем за «битвой титанов».
Вот так это выглядит:
В ближайшее время хочу еще прикрутить автообновление, чтобы каждые 5 минут скачивались только новые точки и добавлялись в график. Но глюков в библиотечке пока довольно много, при не очень стандартных действиях.
И напоследок несколько ссылок:
Официальный сайт Highcharts и Highstock
Дока по Highstock API
Официальный сайт amСharts
До этого использовал 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