- Лидировала ли команда с начала сезона или совершила героический рывок в конце?
- Как зимнее трансферное окно повлияло на результаты?
- Доигрывали ли сезон команды в середине таблицы или играли в полную силу?
Статичная таблица не даёт ответов.
Поиски удачной визуализации сезона на просторах интернета закончились безуспешно, поэтому я начал экспериментировать сам.
Графики или быстро теряли читаемость с ростом количеством команд, или требовали нетривиальной концентрации при первом контакте. В итоге, всё закончилось тем, с чего началось — таблицей. Точнее, скриптом, который преобразовывает результаты сезона в интерактивную таблицу. Можно посмотреть результаты после любого тура или просто нажать на replay и наблюдать, как команды плавают вверх и вниз по таблице:
> Живая демонстрация
Входные данные
Найти результаты любого хоть сколь-нибудь популярного чемпионата не проблема, спасибо огромной букмекерской индустрии. Для демонстрации я возьму результаты матчей английской Премьер-лиги на Football Data:
Date | Home Team | Score | Away Team | Score |
---|---|---|---|---|
August 8, 2015 | Bournemouth | 0 | Aston Villa | 1 |
August 8, 2015 | Chelsea | 2 | Swansea | 2 |
August 8, 2015 | Everton | 2 | Watford | 2 |
... | ... | ... | ... | ... |
Скрипт парсит csv-файл, преобразовывает данные в удобные для представления javascript-объекты и добавляет дополнительную информацию —например, количество побед, ничей и поражений после каждого тура.
Использование
- Подключаем стили в
head
:
<link rel="stylesheet" type="text/css" href="cdn.jsdelivr.net/replay-table/latest/replay-table.css">
- Добавляем скрипт в конец
body
:
<script type="text/javascript" src="//cdn.jsdelivr.net/replay-table/latest/replay-table.min.js"></script>
- Помещаем на страницу
div
с классомreplayTable
и ссылкой на csv-файл в атрибутеdata-csv
:
<div class="replayTable" data-csv="https://s3-us-west-2.amazonaws.com/replay-table/csv/football/england/premier-league/2015-2016.csv" data-table-name="Premier League" data-input-type="listOfMatches" data-item-name="Team" data-use-rounds-numbers="true" </div>
Готово:
Настройка
Внимательный читатель уже заметил
data-
атрибуты. С их помощью таблица адаптируется под разные виды спорта, локализируется и меняет внешний вид. Подробная документация есть на Гитхабе.Я постарался сделать так, чтобы скрипт без доработки можно было использовать для как можно большего числа видов спорта. На сайте таблиц есть примеры вместе с исходным кодом:
- Формула 1, где не бывает результатов матчей.
- NBA, где важно не количество очков, а доля побед.
- Спортивная версия «Что? Где? Когда?» с таблицей на русском.
Лицензия
Используйте таблицы на любых сайтах, в том числе коммерческих.
> Код на Гитхабе.
Спасибо Даше за красоту.
Комментарии (22)
Writerim
27.12.2016 13:51Идея хорошая, но я запомнил положение участников, потом они «сбрасываются» вниз и… я не помню кто куда переместился. Сделать бы изменения только тех позиций, которые реально менялись.
antoniokov
28.12.2016 22:51Не совсем понял. Можете привести пример или прикрепить гифку, пожалуйста?
Сортировка в таблицах устойчивая, команды перемещаются только при изменении позиции.
m_z
27.12.2016 15:03Отлично. Недавно понадобилось сделать такую же анимацию, нашелся только старенький jquery-плагин.
Единственное пожелание: добавьте файл лицензии (MIT или другую), чтобы можно было спокойно использовать в коммерческих проектах.
ConceptDesigner
28.12.2016 14:53Идея хорошая. На мой взгляд, интерактивность должна подразумевать большую вовлеченность пользователя в процесс взаимодействия. Еще было бы интересно, если бы таблица позволяла делать прогноз на следующий тур.
vmm86
28.12.2016 14:53Полезная штука.
Хорошо бы добавить опцию, чтобы подсветка не исчезала, а оставалась бы до обновления таблицы или принудительного сброса на стартовое значение. Так легче отслеживать динамику.
Aw55
28.12.2016 14:53Такие таблицы очень легко делаются с помощью d3.js, если вдруг кому понадобится.
antoniokov
28.12.2016 22:56Вполне вероятно, что и я перепишу анимацию на d3.js вместо React Flip Move.
Singapura
28.12.2016 14:53Добавите статистику по динамике кэфов от букмекеров для каждой из команд(в чемпионате) и будет Супер. Видеть надёжность команд в отрабатывании ожиданий, это ценно.
MOTORIST
28.12.2016 14:53Движения для всех команд тяжело для восприятия. Лучше показать движение одной команды.
antoniokov
28.12.2016 22:58Можно сфокусироваться на одной или нескольких командах через параметр data-focused-items.
maxzuber
28.12.2016 14:54+1Получается довольно любопытный виджет, спасибо. Благодатная тема для исследования и совершенствования, поскольку в каждом чемпионате свои нюансы при равенстве очков. Вижу естественным развитием вынесение конфигурации чемпионата в файл с данными. Причём, в формате JSON, а не CSV, всё-таки.
В самой анимации смущает изменение номера места до перемещения. Может, лучше разбить на три этапа? Начисление очков, сортировка, обновление номера.antoniokov
28.12.2016 23:03Всё так. Скорее всего, для начала добавлю параметр data-tie-breaking с заготовками для дополнительных показателей количество побед, забитые голы и т.п. Если будет не хватать, добавлю опцию конфигурационного JSON-файла.
Я пробовал сделать обновление в несколько этапов — интуитивно казалось, что так хуже.
1ax
03.01.2017 12:36Неплохо было бы разделать css на тот что относится именно к таблице и общий, относящийся к странице. Потому что если подключить все по инструкции в существующий сайт будет конфликт определения заголовков h2 и некоторых других общеупотребимых тегов.
Так же идет ссылка на локально расположенные шрифты, про которых в инструкции ничего нет, что выдает ошибку валидатора.antoniokov
03.01.2017 12:42Это очень хорошие замечания, спасибо.
Мы сделали ошибку, не разделив скрипт и демонстрационный сайт, из-за чего вылезли проблемы с CSS и шрифтами. Сайт в новогоднюю ночь сел на Jekyll и переехал в отдельный репозиторий: https://github.com/TargetProcess/replayTable.com. В ближайшее время вычистим лишнее из файлов самого скрипта — и всё станет хорошо.
1ax
04.01.2017 10:55сформировал вот такой файлик исходных данных — чо-то не работает.
2 Дивизион ЦентрDate,HomeTeam,FTHG,AwayTeam,FTAG
20.07.2016, Арсенал-2,0, Зенит Пз,0
20.07.2016, Торпедо М,2, Чертаново,1
20.07.2016, Авангард К,2, Энергомаш,0
20.07.2016, Сатурн,1, Металлург Лп,1
20.07.2016, Орёл,1, Калуга,0
20.07.2016, Витязь,1, Рязань,0
28.07.2016, Торпедо М,2, Витязь,1
28.07.2016, Зенит Пз,0, Орёл,0
28.07.2016, Металлург Лп,2, Рязань,2
28.07.2016, Сатурн,1, Авангард К,1
28.07.2016, Энергомаш,1, Динамо Бр,0
29.07.2016, Калуга,2, Чертаново,0
04.08.2016, Арсенал-2,0, Энергомаш,6
04.08.2016, Чертаново,1, Зенит Пз,1
04.08.2016, Авангард К,1, Металлург Лп,0
04.08.2016, Динамо Бр,0, Сатурн,1
04.08.2016, Рязань,2, Торпедо М,1
04.08.2016, Витязь,1, Калуга,0
11.08.2016, Зенит Пз,0, Витязь,5
11.08.2016, Металлург Лп,0, Торпедо М,2
11.08.2016, Авангард К,1, Динамо Бр,0
11.08.2016, Сатурн,1, Арсенал-2,1
11.08.2016, Энергомаш,4, Орёл,0
12.08.2016, Калуга,1, Рязань,0
18.08.2016, Арсенал-2,1, Авангард К,2
18.08.2016, Орёл,1, Сатурн,0
18.08.2016, Чертаново,1, Энергомаш,4
18.08.2016, Торпедо М,1, Калуга,1
18.08.2016, Динамо Бр,1, Металлург Лп,0
18.08.2016, Рязань,2, Зенит Пз,0
25.08.2016, Авангард К,0, Орёл,0
25.08.2016, Динамо Бр,5, Арсенал-2,0
25.08.2016, Сатурн,1, Чертаново,2
28.08.2016, Металлург Лп,1, Калуга,0
28.08.2016, Зенит Пз,1, Торпедо М,1
28.08.2016, Энергомаш,2, Витязь,0
02.09.2016, Чертаново,0, Авангард К,1
02.09.2016, Арсенал-2,1, Металлург Лп,3
02.09.2016, Орёл,0, Динамо Бр,1
02.09.2016, Рязань,1, Энергомаш,3
02.09.2016, Витязь,2, Сатурн,1
03.09.2016, Калуга,2, Зенит Пз,2
09.09.2016, Арсенал-2,2, Орёл,2
10.09.2016, Энергомаш,0, Торпедо М,0
10.09.2016, Сатурн,1, Рязань,0
10.09.2016, Динамо Бр,0, Чертаново,2
10.09.2016, Металлург Лп,2, Зенит Пз,4
11.09.2016, Авангард К,3, Витязь,0
16.09.2016, Чертаново,0, Арсенал-2,1
17.09.2016, Калуга,1, Энергомаш,1
17.09.2016, Орёл,0, Металлург Лп,1
17.09.2016, Витязь,1, Динамо Бр,0
17.09.2016, Рязань,1, Авангард К,1
18.09.2016, Торпедо М,1, Сатурн,2
25.09.2016, Сатурн,1, Калуга,1
25.09.2016, Динамо Бр,0, Рязань,0
25.09.2016, Арсенал-2,1, Витязь,2
25.09.2016, Орёл,1, Чертаново,3
25.09.2016, Авангард К,0, Торпедо М,1
26.09.2016, Энергомаш,5, Зенит Пз,1
01.10.2016, Калуга,2, Авангард К,0
01.10.2016, Торпедо М,1, Динамо Бр,1
02.10.2016, Витязь,3, Орёл,2
02.10.2016, Зенит Пз,0, Сатурн,1
02.10.2016, Чертаново,1, Металлург Лп,2
02.10.2016, Рязань,2, Арсенал-2,1
09.10.2016, Арсенал-2,1, Торпедо М,2
09.10.2016, Чертаново,3, Витязь,3
09.10.2016, Динамо Бр,0, Калуга,0
09.10.2016, Орёл,1, Рязань,1
09.10.2016, Металлург Лп,0, Энергомаш,4
09.10.2016, Авангард К,1, Зенит Пз,0
15.10.2016, Калуга,1, Арсенал-2,0
16.10.2016, Торпедо М,1, Орёл,1
16.10.2016, Зенит Пз,1, Динамо Бр,3
16.10.2016, Металлург Лп,0, Витязь,0
16.10.2016, Рязань,2, Чертаново,2
16.10.2016, Энергомаш,0, Сатурн,1
23.10.2016, Чертаново,4, Калуга,0
23.10.2016, Динамо Бр,1, Энергомаш,0
23.10.2016, Авангард К,2, Сатурн,2
23.10.2016, Витязь,1, Торпедо М,3
23.10.2016, Орёл,3, Зенит Пз,1
23.10.2016, Рязань,1, Металлург Лп,1
29.10.2016, Калуга,2, Витязь,1
30.10.2016, Торпедо М,1, Рязань,1
30.10.2016, Металлург Лп,1, Авангард К,0
30.10.2016, Энергомаш,4, Арсенал-2,0
30.10.2016, Зенит Пз,3, Чертаново,0
30.10.2016, Сатурн,1, Динамо Бр,0
06.11.2016, Витязь,3, Зенит Пз,1
06.11.2016, Арсенал-2,1, Сатурн,3
06.11.2016, Динамо Бр,0, Авангард К,1
06.11.2016, Торпедо М,1, Металлург Лп,0
06.11.2016, Рязань,1, Калуга,2
06.11.2016, Орёл,1, Энергомаш,1antoniokov
06.01.2017 00:00И вправду, был баг, при котором таблица не работала, если команды сыграли разное количество туров.
Выпустил новый релиз с фиксом и протестировал вашу таблицу: https://replaytable.com/tables/requests/2016/1ax-russian-second-division-centre.html. Кстати, локализировал её и добавил общее количество туров, чтобы прогресс-бар показывал правду — загляните в исходный код.
В следующем релизе поправим стили, про которые вы писали сверху.
Smi1e
Мне нравится очень информативная графика изменения позиций пилотов на протяжении гонки в той же F1. Легко проследить динамику конкретного пилота.
maxzuber
Тут важный нюанс, что у гонщика есть стартовая позиция, да и в ходе гонки она определяется физическим положением болида. В футбольном чемпионате физических ограничений нет, в начальной стадии точно будет беспрерывная чехарда.
antoniokov
Чехарды в начале меньше, если расставить команды по результатам прошлого сезона. Но всё равно «обгонов» будет в разы больше, чем в любой формульной гонке.
Smi1e
Можно сделать побольше горизонтальный масштаб (расстояние между турами) и читаемость значительно повысится.
Да и брать за отсечку не обязательно начало чемпионата. Расставить можно сразу по результатам 1-го тура, там даже будет правильнее.