воскресенье, 19 декабря 2010 г.

Web: Tree-graph visualization in javascript

Возникло желание нарисовать на web диаграмму в виде дерева, в стиле "Исаак родил Иакова; Иаков родил Иуду". И при этом позволить перетаскивать элементы дерева, и сохранять расположение нод.

Оказалось что задача вовсе не тривальна и состоит как минимум из трех частей:
  • Раскладка графа в виде дерева
  • Рисование соединительных линии между блоками
  • Возможность сохранения и восстановления результата.


Я попытался найти готовую JavaScript библиотеку для этого. Вот что из этого вышло:

Dracula Graph Library

Рисует используя SVG и обладает очень простым синтаксисом. К сожалению библиотека представляет лишь один метод визуализации графа:



При этом синтаксис очень прост:
window.onload = function() {
    var g = new Graph();
    g.addNode("Root");
    g.addNode("Vasy");
    g.addNode("Pety");
    g.addNode("Sasha");
    g.addNode("Masha");
    g.addNode("Katy");
    g.addNode("Misha");
    g.addEdge("Root", "Vasy");
    g.addEdge("Root", "Pety");
    g.addEdge("Vasy", "Sasha");
    g.addEdge("Vasy", "Masha");
    g.addEdge("Pety", "Katy");
    g.addEdge("Pety", "Misha");
    var layouter = new Graph.Layout.Spring(g);
    layouter.layout();
    var renderer = new Graph.Renderer.Raphael('canvas', g, width, height);
    renderer.draw();
 


Если бы была возможность раскладывать граф в дерево и сохранять в JSON расположение нод, то это была бы идеальная библиотека для моих целей.


js-graph-it



Тут сами ноды и соединения задается в виде набора html тэгов с предопределенными классами.

<p class="block draggable" style="top: 100px; left: 10px; width: 300px;" id="par_1">
Ioan
</p>
<p class="block draggable" style="top: 200px; left: 100px; width: 300px;" id="par_2">
Yakov
</p>
<p class="block draggable" style="top: 300px; left: 100px; width: 300px;" id="par_3">
Iuda
</p>
<p class="block draggable" style="top: 400px; left: 100px; width: 300px;" id="par_4">
Vasy
</p>
<div class="connector par_1 par_2">
    <img class="connector-end" src="arrow.gif">
</div>
<div class="connector par_2 par_3">
    <img class="connector-end" src="arrow.gif">
</div>
<div class="connector par_2 par_4">
    <img class="connector-end" src="arrow.gif">
</div>
 

К сожалению библиотека требует, чтобы в разметке уже была рассчитана начальная раскаладка графа. Это удобно лишь для отрисовки статических графов, но для рисования динамических нужно самому реализовывать расчет местоположения всех нод.
К плюсам можно отнести то, что все соединения рисуются стандартными div'ами т.е. работать будет почти везде, но при этом все связи будут состоять из вертикальных или горизонтальных линии, кривых и диагональных нет.

Пока найти 100% подходящую под мои требования библиотеку, мне не удалось. :(
Вот обсуждение на StackOferflow этих и других библиотек.

Комментариев нет: