Pull to refresh

Highstock: мониторим Премию Рунета

Reading time4 min
Views8.1K
Долгое время в своих проектах использовал Flash-графики, вместо обычных картинок. Они и красивее и более функциональны, да и серверу не нужно напрягаться для генерации картинок. Но в связи с тем, что некоторые фирмы не очень дружат с Flash, пришлось поискать замену без использования Flash.

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

Сбор данных


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

Подготовку особо расписывать не буду, в общих чертах. Так как к самой премии не имею никакого отношения, поэтому просто написал PHP-скрипт, который, скачивает главную страницу, парсит её регулярками, после чего количество голосов и позиции заносит в базу. Скрипт повешен на крон и выполняется каждые 5 минут.

Подготовка данных


Итак, данные есть, теперь нужно подумать, как их выводить. Поскольку сайтов принимающих участие в голосовании 50 штук, плюс разрывы между сайтами составляют 2 порядка, то выводить все сайты вместе не имеет смысла. Немного пораскинув мозгами, остановился на следующих вариантах вывода:
  1. По умолчанию, выводятся первые 3 позиции.
  2. Диапазоны по 10 позиций (1-10,11-20 и т.п.).
  3. Выбор конкретных сайтов (1,3,10).
  4. Если выбран только один сайт, то показываются также его ближайшие конкуренты, один на позицию выше, другой на позицию ниже.
Дальше нужно определиться с форматом генерируемых данных. В Highstock понимает 3 варианта.
  1. Простой массив со значениями для оси Y, в таких случаях значения по X рассчитываются автоматически в соответствии с указанными правилами.
    data: [0, 5, 3, 5]
  2. Массив, содержащий значения X,Y.
    data: [[5, 2], [6, 3], [8, 2]]
  3. Массив объектов — самый продвинутый вариант, позволяющий хоть каждую точку настраивать.
    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
Tags:
Hubs:
Total votes 46: ↑41 and ↓5+36
Comments12

Articles