Pull to refresh

Турнирная таблица на SVG

Reading time3 min
Views3.8K
Решил сделать интерактивную турнирную таблицу-график для футболного чемпионата России. Вот такую:

image

Выбор инструментов был прост:
  • табличка для браузера — значит, что-нибудь из вэб-технологий;
  • нужна векторная графика;
  • никаких закрытых либо сложных приложений при создании — я все-таки не вэб-дизайнер.

В итоге выбор естественным образом пал на связку SVG+JavaScript (что, правда, исключило IE из списка поддерживаемых браузеров).

Итак поехали.

Первым делом в JavaScript-секции определяем параметры турнира и внешнего вида таблицы:

var nTeams = 16, nTours = (nTeams - 1) * 2, nToursPlayed = nTours;
var vPad = 30, vIndent = 0, hPad = 20, hIndent = 65;


Ура. Теперь можно рисовать — для начала турнирную сетку. Определяем команды и координаты (M — MoveTo, H — Horizontal line, V — Vertical line, маленькие буквы означают, что координаты относительные):

// Grid - horizontal lines
path = "M " + (hPad + hIndent) + " " + (vPad + vIndent);
for (i = 0; i < nTeams; i++)
{
  path += "h " + width + " m -" + width + " " + vPad;
}

// Grid path - vertical lines
path += " M " + (hPad*2 + hIndent) + " " + (vPad + vIndent);
for (i = 0; i < nTours; i++)
{
  path += "v " + height + " m " + hPad + " -" + height;
}


Теперь с этими координатами надо что-то делать. Все очень просто — создаем объект «path», определяемый этой строкой, и добавляем его в документ:

grid = svgDocument.createElementNS(svgns, "path");
grid.setAttributeNS(null, "d", path);
grid.setAttributeNS(null, "class", "grid");
svgDocument.documentElement.appendChild(grid);


Теперь с наполнением. Что делать с данными? Запихать в массив. Сколько элементов в массиве? По числу команд. Что представляет из себя каждый элемент массива? Имя команды, цвет команды и дальше по порядку — место в соответствующем туре, например:

["Кр.Советов", "#1E90FF", 4, 2, 4, 2, 3, 1, 4, 5, 3, 3, 3, 4, 6, 7, 7, 8, 11, 9, 9, 9, 9, 9, 10, 10, 12, 9, 9, 9, 10, 10]

И теперь обходим все элементы массива, сначала проставляя метки с названиями команд, потом рисуя график продвижения:

// Create text labels - teams
for (i = 0; i < nTeams; i++)
{
  label = svgDocument.createElementNS(svgns, "text");
  label.setAttributeNS(null, "x", 0);
  label.setAttributeNS(null, "y", vPad * (i + 1) + 4 + vIndent);
  label.appendChild(document.createTextNode(tournamentData[i][0]));
  svgDocument.documentElement.appendChild(label);
}

// Create team tracks
for (i = 0; i < nTeams; i++)
{
  path = "M " + (hPad + hIndent) + " " + (vPad * (i + 1) + vIndent);

  for (j = 0; j < nToursPlayed; j++)
  {
    path += " L " + (hPad * (j + 2) + hIndent) + " " + (vPad * tournamentData[i][j+2] + vIndent);
  }
  path += " L " + (hPad * (nTours + 1) + hIndent) + " " + (vPad * tournamentData[i][nToursPlayed+1] + vIndent);

  teamTrack = svgDocument.createElementNS(svgns, "path");
  teamTrack.setAttributeNS(null, "d", path);
  teamTrack.setAttributeNS(null, "fill", "none");
  teamTrack.setAttributeNS(null, "stroke", tournamentData[i][1]);
  teamTrack.setAttributeNS(null, "stroke-width", 2);
  teamTrack.setAttributeNS(null, "stroke-linejoin", "round");
  teamTrack.setAttributeNS(null, "stroke-linecap", "round");
  svgDocument.documentElement.appendChild(teamTrack);
}


В какой момент рисовать? Да в момент загрузки — весь этот код заносим в функцию makeShape, вызываемую при загрузке документа:

<svg onload="makeShape(evt)" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">

image

Неплохо. Но сложновато отследить продвижение одной команды. Было бы здорово по клику мышки выделять один график. Захотели — сделали:

function highlight(evt, i)
{
  var svgDocument = evt.target.ownerDocument;
  var element = svgDocument.getElementById("track" + i);

  // Trigger highligtning
  if (element.getAttributeNS(null, "stroke-width") == "2")
    element.setAttributeNS(null, "stroke-width", 10);
  else
    element.setAttributeNS(null, "stroke-width", 2);
}


Теперь добавляем вызов этой функции по клику на график (а заодно и присваиваем id графику):

teamTrack.setAttributeNS(null, "id", "track" + i);
teamTrack.setAttributeNS(null, "onclick", "highlight(evt, " + i + ")");


image

Получилось. :) Результат можно посмотреть здесь, а код взять здесь.  :)
Tags:
Hubs:
+24
Comments33

Articles

Change theme settings