2012-06-19 2 views
4

Недавно я узнал о Cytoscape.js и хотел бы попробовать силовые макеты: беседка и пружинящая.Cytoscape.js силовые макеты и размещение узлов

Теперь у меня есть несколько вопросов:

  1. Можно ли достичь граф, используя один из макетов, в которых размещение узла на основе некоторого алгоритма и узла координат не необходимо? Например, в VivaGraphJS график сходится так, что связанные узлы образуют группы и одиночные узлы, перемещающиеся на периферию. Если это можно сделать с помощью направленного на усиление макета, можно ли отключить силы, чтобы узлы могли быть выбраны и свободно перемещены на холсте?

  2. Насколько велики графики (количество узлов/ребер), Cytoscape реально справляется?

  3. Скажите, что каждый узел и край имеют пять атрибутов, и я хочу текстовое поле, которое отображает их при наведении курсора мыши. Какой самый простой способ сделать это?

  4. Wiki говорит, что отдельные узлы могут быть добавлены, как показано ниже, но cy не имеет функции узла; это ошибка? var n0 = cy.node ("n1"); cy.add (n0); // добавьте один элемент, n0

  5. Я попытался создать тривиальный случайный граф данных, который использует Arbor/Springy. Код ниже дает ошибку «данные не определены» в «return data.cy». Когда макет «случайный», код работает. Что я делаю не так?

<!DOCTYPE html> 
<html> 
<head> 
    <title>Test</title> 
    <style type="text/css"> 
    .full-height { height: 600px; margin: 0 0; padding: 0 0; } 
    </style> 

    <script src="jquery-1.7.2.js"></script> 
    <script src="demo/cytoscape.all.js"></script> 
    <script src="demo/extensions/cytoscape.layout.arbor.js"></script> 
    <script src="demo/extensions/cytoscape.layout.springy.js"></script> 


    <script src="demo/arbor.js"></script> 
    <script src="demo/arbor-tween.js"></script> 
    <script src="demo/springy.js"></script> 


    <script type='text/javascript'> 
     function onLoad() { 

      // create a mapper for node size 
      var nodeSizeMapper = { 
       continuousMapper: { 
        attr: { 
         name: "weight", 
         min: 0, 
         max: 40 
        }, 
        mapped: { 
         min: 5, 
         max: 25 
        } 
       } 
      }; 

      $("#cy").cytoscape({ 
       layout: { name: "arbor" }, // works when "random" 
       style: { 
        selectors: { 
         "node":{ 
          shape: "ellipse", 
          fillColor: "#3366FF", 
          height: nodeSizeMapper, 
          width: nodeSizeMapper, 
          labelText: { 
           passthroughMapper: "id" 
          } 
         }, 
         "edge": { 
          lineColor: "#CCFF33",//"#ccc", 
          targetArrowColor: "#CCFF33", //"#ccc", 
          width: { 
           continuousMapper: { 
            attr: { 
             name: "weight", 
             min: 20, 
             max: 35 
            }, 
            mapped: { 
             min: 1, 
             max: 3 
            } 
           } 
          }, 
          targetArrowShape: "triangle", 
          // labelText: { 
          //  passthroughMapper: "weight" 
          // } 
         }, 
         "node:selected": { 
          fillColor: "#333" 
         }, 
         "edge:selected":{ 
          lineColor: "#666", 
          targetArrowColor: "#666" 
         } 
        } 
       },      
       ready: function(cy) { }, 
      }); 
      window.cy = $("#cy").cytoscape("get"); 

      $.getJSON('edges_nodes.json', function(elements) { 
       //console.log(elements); 
       window.elements = elements; 
       cy.load(elements); 
      }); 
     } 
    </script> 
</head> 

<body onload="onLoad()"> 
     <div class="full-height" id="cy"> 
     </div> 
</body> 
</html> 

Файл JSON гласит:

{"nodes": [{"classes": "b", "data": {"id": "n0", "weight": 40}}, {"classes": "b", "data": {"id": "n1", "weight": 19}}, {"classes": "c", "data": {"id": "n2", "weight": 0}}, {"classes": "d", "data": {"id": "n3", "weight": 19}}, {"classes": "e", "data": {"id": "n4", "weight": 4}}, {"classes": "a", "data": {"id": "n5", "weight": 21}}, {"classes": "e", "data": {"id": "n6", "weight": 13}}, {"classes": "a", "data": {"id": "n7", "weight": 6}}, {"classes": "a", "data": {"id": "n8", "weight": 10}}, {"classes": "b", "data": {"id": "n9", "weight": 6}}, {"classes": "c", "data": {"id": "n10", "weight": 24}}, {"classes": "c", "data": {"id": "n11", "weight": 14}}, {"classes": "e", "data": {"id": "n12", "weight": 11}}, {"classes": "b", "data": {"id": "n13", "weight": 6}}, {"classes": "e", "data": {"id": "n14", "weight": 24}}, {"classes": "b", "data": {"id": "n15", "weight": 26}}, {"classes": "b", "data": {"id": "n16", "weight": 6}}, {"classes": "c", "data": {"id": "n17", "weight": 36}}, {"classes": "a", "data": {"id": "n18", "weight": 7}}, {"classes": "b", "data": {"id": "n19", "weight": 37}}, {"classes": "c", "data": {"id": "n20", "weight": 28}}, {"classes": "d", "data": {"id": "n21", "weight": 11}}, {"classes": "d", "data": {"id": "n22", "weight": 20}}, {"classes": "e", "data": {"id": "n23", "weight": 7}}, {"classes": "b", "data": {"id": "n24", "weight": 31}}, {"classes": "b", "data": {"id": "n25", "weight": 1}}, {"classes": "e", "data": {"id": "n26", "weight": 29}}, {"classes": "d", "data": {"id": "n27", "weight": 31}}, {"classes": "d", "data": {"id": "n28", "weight": 34}}, {"classes": "b", "data": {"id": "n29", "weight": 40}}, {"classes": "d", "data": {"id": "n30", "weight": 38}}, {"classes": "b", "data": {"id": "n31", "weight": 17}}, {"classes": "a", "data": {"id": "n32", "weight": 39}}, {"classes": "d", "data": {"id": "n33", "weight": 4}}, {"classes": "c", "data": {"id": "n34", "weight": 38}}, {"classes": "d", "data": {"id": "n35", "weight": 13}}, {"classes": "b", "data": {"id": "n36", "weight": 15}}, {"classes": "a", "data": {"id": "n37", "weight": 29}}, {"classes": "a", "data": {"id": "n38", "weight": 2}}, {"classes": "d", "data": {"id": "n39", "weight": 35}}, {"classes": "c", "data": {"id": "n40", "weight": 24}}, {"classes": "c", "data": {"id": "n41", "weight": 7}}, {"classes": "e", "data": {"id": "n42", "weight": 24}}, {"classes": "c", "data": {"id": "n43", "weight": 4}}, {"classes": "d", "data": {"id": "n44", "weight": 40}}, {"classes": "a", "data": {"id": "n45", "weight": 19}}, {"classes": "b", "data": {"id": "n46", "weight": 17}}, {"classes": "b", "data": {"id": "n47", "weight": 36}}, {"classes": "b", "data": {"id": "n48", "weight": 26}}, {"classes": "a", "data": {"id": "n49", "weight": 18}}], "edges": [{"data": {"source": "n5", "id": "e0", "weight": 31, "target": "n19"}}, {"data": {"source": "n37", "id": "e1", "weight": 31, "target": "n25"}}, {"data": {"source": "n19", "id": "e2", "weight": 31, "target": "n2"}}, {"data": {"source": "n16", "id": "e3", "weight": 23, "target": "n27"}}, {"data": {"source": "n29", "id": "e4", "weight": 17, "target": "n4"}}, {"data": {"source": "n1", "id": "e5", "weight": 33, "target": "n12"}}, {"data": {"source": "n13", "id": "e6", "weight": 38, "target": "n33"}}, {"data": {"source": "n12", "id": "e7", "weight": 34, "target": "n4"}}, {"data": {"source": "n32", "id": "e8", "weight": 34, "target": "n13"}}, {"data": {"source": "n44", "id": "e9", "weight": 32, "target": "n19"}}, {"data": {"source": "n31", "id": "e10", "weight": 24, "target": "n19"}}, {"data": {"source": "n35", "id": "e11", "weight": 18, "target": "n48"}}, {"data": {"source": "n25", "id": "e12", "weight": 19, "target": "n15"}}, {"data": {"source": "n31", "id": "e13", "weight": 18, "target": "n16"}}, {"data": {"source": "n24", "id": "e14", "weight": 39, "target": "n27"}}, {"data": {"source": "n47", "id": "e15", "weight": 22, "target": "n3"}}, {"data": {"source": "n1", "id": "e16", "weight": 34, "target": "n35"}}, {"data": {"source": "n22", "id": "e17", "weight": 15, "target": "n5"}}, {"data": {"source": "n37", "id": "e18", "weight": 40, "target": "n10"}}, {"data": {"source": "n37", "id": "e19", "weight": 21, "target": "n29"}}]} 

ответ

5

(1) Да, если указать расположение в настройках инициализации, он будет использоваться для размещения узлов первоначально и не будет необходимо указать расположение узлов. Я думаю, что вариант размещениябудет делать то, что вы просите относительно интерактивности во время беседки.

(2) С SVG-рендерером, примерно так же, как и в старой версии - это не так много. Сейчас я делаю много рефакторинга, чтобы ускорить работу ядра и обработать больше элементов, а новый рендеринг холста, над которым мы работаем, будет надеяться, что мы будем обрабатывать 100 000 элементов (или, может быть, даже 1 000 000 элементов).

(3) Используйте что-то вроде qtip и читайте значения свойств, как обычно, через API cytoscape.js (то есть eles.data()).

(4) К сожалению, API трудно поддерживать в вики, и то, что вы читали, устарело, учитывая меняющийся характер предварительных сборок. Я создаю лучшее решение, и оно скоро закончится.

(5) Вероятно, это ошибка в макете беседки, когда график пуст. В конце концов, вы начинаете с пустого графика. Возможно, обходите это сейчас, инициализируя cytoscape.js в своем обратном вызове $.getJSON()?

+0

Спасибо, что ответили на мои вопросы. (2) У вас есть дата оценки выпуска cytoscape.js и улучшенного рендеринга холста? (5) Не удалось заставить его работать. Оставляя запрос ajax и определяя граф с двумя узлами и одним краем с «элементами», я получаю ту же ошибку с макетом «беседка».Должен ли я использовать определенную версию arbor.js и springy.js? Я просто скачал их со своих сайтов. – amergin

+0

Это все будет сделано к концу лета, самое позднее. Поскольку, вероятно, не будет больше предварительных сборок до тех пор, пока я не поработаю с более большими проблемами в Github, я предлагаю вам попробовать инициализацию со случайным макетом, а затем вызвать макет беседки после 'cy.ready'. ** Редактирование **: Кажется, вы все-таки строитесь из мастер-ветви. Вероятно, это было исправлено. Если нет, сообщите мне, и я отлажу его. – maxkfranz

Смежные вопросы