Некое время назад, мне потребовалось визуализировать графы и хотелось найти уже готовое решение что бы не изобретать очередной велосипед. Мне в руки попалась библиотека arbor, которая используя jQuery предоставлет возможность отрисовывать вполне приемлемые графы в браузере.
Саму библиотеку, а так же документацию и примеры (всё на английском) можно скачать на официальном сайте
И так по порядку.
В качестве холста используется html5 canvas, а это значит что в браузерах его не поддерживающих ничего работать не будет.
Создадим простую страницу которая подгружает JSON данные о вершинах и рёбрах с помощью AJAX. За основу возьмём идущий в комплекте пример и модернизируем его (загрузка данных, отображение).
Создадим файл с данными, где перечислим все вершины и рёбра
data.json:
В основном файле подключим необходимые библиотеки, а так же вынесем во внешний файл все js скрипты
В теле документа создаём canvas в котором будем рисовать
Теперь по порядку как это всё будет работать.
При полной загрузке создаётся объект с настройками для arbor, который так же содержит функции которые будут выполнятся при наступлении различных событий, функции отрисовки каждой вершины и грани (этим мне и понравилась библиотека, что позволяет настроить практически всё).
Далее этот объект передаём в конструктор arbor, который и запустит всю эту карусель.
Загрузка данных также осуществляется сразу после того как страница будет полностью загружена.
Вообще кода здесь больше чем слов, поэтому я считаю будет яснее и понятнее перейти сразу к нему с подробными комментариями.
main.js:
Сама библиотека мне понравилась тем что позволяет самому отрисовывать как будут выглядеть вершины и грани, а так же настроить действия на любые события.
Исходник получившегося можно скачать тут
Саму библиотеку, а так же документацию и примеры (всё на английском) можно скачать на официальном сайте
И так по порядку.
В качестве холста используется html5 canvas, а это значит что в браузерах его не поддерживающих ничего работать не будет.
Создадим простую страницу которая подгружает JSON данные о вершинах и рёбрах с помощью AJAX. За основу возьмём идущий в комплекте пример и модернизируем его (загрузка данных, отображение).
Создадим файл с данными, где перечислим все вершины и рёбра
data.json:
{
"nodes": [
{"name": "node_1"},
{"name": "node_2"},
{"name": "node_3"},
{"name": "node_4"},
{"name": "node_5"},
{"name": "node_6"},
{"name": "node_7"},
{"name": "node_8"},
{"name": "node_9"},
{"name": "node_10"}
],
"edges": [
{"src": "node_3", "dest": "node_2"},
{"src": "node_5", "dest": "node_3"},
{"src": "node_8", "dest": "node_7"},
{"src": "node_1", "dest": "node_4"},
{"src": "node_7", "dest": "node_5"},
{"src": "node_3", "dest": "node_9"},
{"src": "node_2", "dest": "node_4"},
{"src": "node_6", "dest": "node_5"},
{"src": "node_9", "dest": "node_1"},
{"src": "node_10", "dest": "node_2"},
{"src": "node_1", "dest": "node_10"}
]
}
В основном файле подключим необходимые библиотеки, а так же вынесем во внешний файл все js скрипты
<script src="js/jquery.min.js"></script>
<script src="js/arbor.js"></script>
<script src="main.js"></script>
В теле документа создаём canvas в котором будем рисовать
<canvas id="viewport" width="800" height="600"></canvas>
Теперь по порядку как это всё будет работать.
При полной загрузке создаётся объект с настройками для arbor, который так же содержит функции которые будут выполнятся при наступлении различных событий, функции отрисовки каждой вершины и грани (этим мне и понравилась библиотека, что позволяет настроить практически всё).
Далее этот объект передаём в конструктор arbor, который и запустит всю эту карусель.
Загрузка данных также осуществляется сразу после того как страница будет полностью загружена.
Вообще кода здесь больше чем слов, поэтому я считаю будет яснее и понятнее перейти сразу к нему с подробными комментариями.
main.js:
(function($){
var Renderer = function(canvas)
{
var canvas = $(canvas).get(0);
var ctx = canvas.getContext("2d");
var particleSystem;
var that = {
init:function(system){
//начальная инициализация
particleSystem = system;
particleSystem.screenSize(canvas.width, canvas.height);
particleSystem.screenPadding(80);
that.initMouseHandling();
},
redraw:function(){
//действия при перересовке
ctx.fillStyle = "white"; //белым цветом
ctx.fillRect(0,0, canvas.width, canvas.height); //закрашиваем всю область
particleSystem.eachEdge( //отрисуем каждую грань
function(edge, pt1, pt2){ //будем работать с гранями и точками её начала и конца
ctx.strokeStyle = "rgba(0,0,0, .333)"; //грани будут чёрным цветом с некой прозрачностью
ctx.lineWidth = 1; //толщиной в один пиксель
ctx.beginPath(); //начинаем рисовать
ctx.moveTo(pt1.x, pt1.y); //от точки один
ctx.lineTo(pt2.x, pt2.y); //до точки два
ctx.stroke();
});
particleSystem.eachNode( //теперь каждую вершину
function(node, pt){ //получаем вершину и точку где она
var w = 10; //ширина квадрата
ctx.fillStyle = "orange"; //с его цветом понятно
ctx.fillRect(pt.x-w/2, pt.y-w/2, w,w); //рисуем
ctx.fillStyle = "black"; //цвет для шрифта
ctx.font = 'italic 13px sans-serif'; //шрифт
ctx.fillText (node.name, pt.x+8, pt.y+8); //пишем имя у каждой точки
});
},
initMouseHandling:function(){ //события с мышью
var dragged = null; //вершина которую перемещают
var handler = {
clicked:function(e){ //нажали
var pos = $(canvas).offset(); //получаем позицию canvas
_mouseP = arbor.Point(e.pageX-pos.left, e.pageY-pos.top); //и позицию нажатия кнопки относительно canvas
dragged = particleSystem.nearest(_mouseP); //определяем ближайшую вершину к нажатию
if (dragged && dragged.node !== null){
dragged.node.fixed = true; //фиксируем её
}
$(canvas).bind('mousemove', handler.dragged); //слушаем события перемещения мыши
$(window).bind('mouseup', handler.dropped); //и отпускания кнопки
return false;
},
dragged:function(e){ //перетаскиваем вершину
var pos = $(canvas).offset();
var s = arbor.Point(e.pageX-pos.left, e.pageY-pos.top);
if (dragged && dragged.node !== null){
var p = particleSystem.fromScreen(s);
dragged.node.p = p; //тянем вершину за нажатой мышью
}
return false;
},
dropped:function(e){ //отпустили
if (dragged===null || dragged.node===undefined) return; //если не перемещали, то уходим
if (dragged.node !== null) dragged.node.fixed = false; //если перемещали - отпускаем
dragged = null; //очищаем
$(canvas).unbind('mousemove', handler.dragged); //перестаём слушать события
$(window).unbind('mouseup', handler.dropped);
_mouseP = null;
return false;
}
}
// слушаем события нажатия мыши
$(canvas).mousedown(handler.clicked);
},
}
return that;
}
$(document).ready(function(){
sys = arbor.ParticleSystem(1000); // создаём систему
sys.parameters({gravity:true}); // гравитация вкл
sys.renderer = Renderer("#viewport") //начинаем рисовать в выбраной области
$.getJSON("data.json", //получаем с сервера файл с данными
function(data){
$.each(data.nodes, function(i,node){
sys.addNode(node.name); //добавляем вершину
});
$.each(data.edges, function(i,edge){
sys.addEdge(sys.getNode(edge.src),sys.getNode(edge.dest)); //добавляем грань
});
});
})
})(this.jQuery)
Сама библиотека мне понравилась тем что позволяет самому отрисовывать как будут выглядеть вершины и грани, а так же настроить действия на любые события.
Исходник получившегося можно скачать тут