Недавно я писал о библиотеке Flot , предназначенной для создания динамических графиков средствами JavaScript. Dracula — это аналогичная библиотека для работы с графами.
Это интересно: Название библиотеки представляет собой игру слов — Граф Дракула, Dracula Graph Library.
На момент написания этого поста последней версией библиотеки была 0.0.3 alpha. Несмотря на свой малый возраст, уже сейчас Dracula умеет создавать достаточно сложные динамические графы . «Динамические» означает, что узлы графа можно перетаскивать мышью. «Достаточно сложные» — в плане оформления, а не числа узлов и ребер.
Пользоваться библиотекой — одно удовольствие:
< head >
< title > Dracula Test < / title >
<!— подключаем необходимые js-файлы —>
< script type = «text/javascript» src = «js/raphael-min.js» >
< / script >
< script type = «text/javascript» src = «js/dracula_graffle.js» >
< / script >
< script type = «text/javascript» src = «js/dracula_graph.js» >
< / script >
< / head >
< body >
<!— здесь будет выведен граф —>
< div id = «canvas» >< / div >
< script language = «javascript» type = «text/javascript» >
var g = new Graph();
// добавляем узел с id «bebebe» и подписью «stand alone»
// последний аргумент метода addNode — необязательный
g.addNode(«bebebe», { label: «stand alone» });
for(var i = 1; i < = 13 ; i++ ) {
// метод addEdge ( a, b ) создает ребро между узлами а и b
// если узлы a и b еще не созданы, они создадутся автоматически
g.addEdge ( i, ( i + 3 ) % 5 + 1 ) ;
var j = ( i + 7 ) % 5 + 1 ;
// можно указать дополнительные свойства ребра
g.addEdge ( i, j, {
directed: true, // ориентированное ребро
stroke: «#fff» , fill: «#5a5» , // цвета ребра
label : i+ «:» +j } ) ; // надпись над ребром
}
// вычисляем расположение вершин перед выводом
var layouter = new Graph.Layout.Spring ( g ) ;
layouter.layout ( ) ;
// выводим граф
var renderer = new Graph.Renderer.Raphael ( ‘canvas’ , g, 512 , 368 ) ;
renderer.draw ( ) ;
< / script >
< / body >
< / html >
Данный код выводит вот такую красоту:
Здесь я раскидал вершины подальше друг от друга — сама библиотека не всегда располагает их самым удачным образом. Еще один обнаруженный мной косяк — иногда во время перемещения вершины «улетают» за пределы холста и не желают оттуда возвращаться. Кроме того, библиотека довольно требовательна к ресурсам.
Приведенный пример работает на моем компьютере с небольшими тормозами, но они практически незаметны. Аналогичный граф, состоящий из 30 вершин, рисуется около трех секунд и ощутимо тормозит при перетаскивании вершин. На создание графа из 100 вершин уходит целых 5 секунд, что уже совершенно неприемлемо.
Однако при этом библиотека неплохо справляется с деревом, состоящим из 121-го узла (ему, конечно, нужен холст побольше, чем 512×368, как в приведенном примере). Таким образом, производительность Dracula в первую очередь зависит от структуры графа . Код для построения дерева:
var counter = 1 ;
g. addNode ( «x» , { label : «1» } ) ;
buildTree ( «x» , 4 ) ;
function buildTree ( node , level ) {
var left = node + «l» ;
var right = node + «r» ;
var center = node + «c» ;
g. addNode ( left , { label : ++ counter } ) ;
g. addNode ( right , { label : ++ counter } ) ;
g. addNode ( center , { label : ++ counter } ) ;
g. addEdge ( node , left ) ;
g. addEdge ( node , right ) ;
g. addEdge ( node , center ) ;
if ( level > 1 ) {
buildTree ( left , level — 1 ) ;
buildTree ( right , level — 1 ) ;
buildTree ( center , level — 1 ) ;
}
}
Несмотря на недостатки библиотеки, я бы советовал держать ее на вооружении. Во-первых, в будущем производительность Dracula может быть улучшена (а может, на всех ПК будут 16-и ядерные процессоры?). Во-вторых, если вам нужно вывести схему локалки из десятка компьютеров или небольшую нейронную сеть , библиотека вполне справится с задачей.
На официальном сайте Dracula вы найдете пример кода , выводящего граф с вершинами произвольной формы. А в этом архиве находится приведенный в заметке пример вместе с библиотекой версии 0.0.3 alpha.
Дополнение: См также мой пост Рисуем красивые графы при помощи Graphviz .