2017-02-15 4 views
3

Hi Stackoverflow Community!Динамически изменяет размер div, когда он используется как узел в d3-силовом графике

Итак, моя проблема заключается в следующем:

У меня есть d3 сила-ориентированный граф. Узлы этого графа являются div. Теперь я хочу, чтобы иметь возможность изменять размер этого divs с помощью мыши. Для этой цели я использую jqueryui resizable().

К сожалению, это делает изменения ui (когда я достигаю краев узла, я получаю mousesymbol для изменения размера), но я не могу изменять их размер. Я считаю, что это потому, что d3-forcegraph накладывает функцию jqueryui. Я попытался остановить график, чтобы получить доступ к функциям изменения размера, но это, похоже, не сработает.

Есть ли у кого-нибудь идеи, как я могу сделать эти divs изменяемыми по размеру? Я создал скрипку, чтобы показать, что я имею в виду: https://jsfiddle.net/5jgrf5h8/

//constants for the network visualisation 
var height = window.innerHeight-20; //fullsize svg 
var width = window.innerWidth-20; 


var nodes = [ 
    {"id": "RootNode", "group": 0}, 
    {"id": "Node1", 
     "ip_adresses": [ 
     {"ip_adress": "aa.bbb.114.80/28"} 
     ], 
     "group": 1}, 
    {"id": "Node2", 
     "ip_adresses": [ 
     {"ip_adress": "aa.bbb.117.96/28"} 
     ], 
     "group": 1}, 
    {"id": "Node3", 
     "ip_adresses": [ 
     {"ip_adress": "eeee:ffff:400:3001::7"}, 
     {"ip_adress": "eeee:ffff:400:3001::8"}, 
     {"ip_adress": "eeee:ffff:400:3001::9"}, 
     {"ip_adress": "eeee:ffff:400:3001::10"}, 
     {"ip_adress": "eeee:ffff:400:3001::11"}, 
     {"ip_adress": "eeee:ffff:400:3001::12"}, 
     {"ip_adress": "eeee:ffff:400:3001::13"}, 
     {"ip_adress": "eeee:ffff:400:3001::14"}, 
     {"ip_adress": "eeee:ffff:400:3001::15"}, 
     {"ip_adress": "eeee:ffff:400:3001::16"}, 
     {"ip_adress": "eeee:ffff:400:3001::17"} 
     ], 
     "group": 1}, 
    {"id": "Node4", 
     "ip_adresses": [ 
     {"ip_adress": "cc.dd38.151"}, 
     {"ip_adress": "cc.dd38.152"} 
     ], 
     "group": 1}, 
    {"id": "Node5", 
     "ip_adresses": [ 
     {"ip_adress": "aa.bbb.114.36"}, 
     {"ip_adress": "aa.bbb.114.37"} 
     ], 
     "group": 1} 
    ]; 

var links = [ 
    {"source": "RootNode", "target": "Node1", "value": 140}, 
    {"source": "RootNode", "target": "Node2", "value": 140}, 
    {"source": "RootNode", "target": "Node3", "value": 140}, 
    {"source": "RootNode", "target": "Node4", "value": 140}, 
    {"source": "RootNode", "target": "Node5", "value": 140} 
    ]; 

var color = d3.scaleOrdinal(d3.schemeCategory10); 

//creating and configuring the d3 force-directed graph simulation 
var simulation = d3.forceSimulation() 
     .force("charge", d3.forceManyBody().strength(-2000)) 
     .force("center", d3.forceCenter(width/2, height/2)) 
     .force("link", d3.forceLink() 
     .distance(function(d){return d.value;}) 
     .strength(1.3).id(function(d){return d.id;})); 

//create a svg in the body of index.html 
var svg = d3.select("body").append("svg") 
    .classed("simulation", 1) 
    .attr("width", width) 
    .attr("height", height); 

//setting the links 

var glink = svg.append("g") 
.attr("class", "links") 
.selectAll("links") 
.data(links).enter(); 

var link = glink.append("polyline") 
.attr("stroke-width", 2); 



//setting the nodes. they will be div elements 
var node = d3.select("body") 
    .append("div") 
    .attr("class", "nodes") 
    .selectAll(".node") 
    .data(nodes) 
    .enter().append("div") 
    .attr("class", "node") 
    .attr("id", function(d){return d.id;}) 
    .style("background", function(d) { return color(d.group); }); 


node.each(function (d, i){ 
    if(d.group === 1) 
    { 
    console.log(d.id, i, d3.select(this).attr("id")); 

    d3.select(this).append("select") 
    .attr("size", 2) 
    .selectAll('option') 
    .data(nodes[i].ip_adresses) 
    .enter() 
    .append("option") 
    .text(function(d){return d.ip_adress;}); 
    } 
    else 
    { 
    d3.select(this).text(function (d){return d.id;}); 
    } 
}); 



//start the simulation 
node.call(d3.drag() 
.on("start", dragstarted) 
.on("drag", dragged) 
.on("end", dragended)); 


//assigning data to the simulation and set tick 
simulation 
.nodes(nodes) 
.on("tick", ticked); 

simulation.force("link") 
.links(links); 

function ticked() { 

link.attr("points", function(d) { 

    var sourceX = d.source.x; 
    var sourceY = d.source.y; 
    var targetX = d.target.x; 
    var targetY = d.target.y; 

    return sourceX + "," + sourceY + " " + 
    (sourceX + targetX)/2 + "," + (sourceY + targetY)/2 + " " + 
    targetX + ", " + targetY; 
}); 

node.style('left', function(d ,i) { 
    return d.x-$("[id='"+d.id+"']").outerWidth()/2+"px"; 
}) 
.style('top', function(d) { 
    return d.y-$("[id='"+d.id+"']").outerHeight()/2+"px"; 
}); 

} 

d3.select("body").selectAll("option").on("dblclick", function(){ 
    alert(this.text); 
}); 

//this would be nice but it is not working in the d3 graph 
$(".node").resizable(); 


function dragstarted(d) { 
    if (!d3.event.active) simulation.alphaTarget(0.3).restart(); 
    d.fx = d.x; 
    d.fy = d.y; 
} 

function dragged(d) { 
    d.fx = d3.event.x; 
    d.fy = d3.event.y; 
    d.fixed = true; 
} 

function dragended(d) { 
    if (!d3.event.active) simulation.alphaTarget(0); 
    d.fx = null; 
    d.fy = null; 
} 

ответ

2

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

node.call(d3.drag() 
.on("start", dragstarted) 
.on("drag", dragged) 
.on("end", dragended)); 

Причина: они съедают событие поэтому JQUERY resizable не будет работать.

Второй дополнительный класс ваш выбор, так что они уникальны (будут использоваться для выбора Jquery):

d3.select(this).append("select") 
    .attr("size", 2) 
    .attr("class", function(){ return "my-list" + i;})//giving unique class to all select. 

Третье дополнение изменение размера (alsoResize), чтобы выбрать уникальные имена классов, сделанные выше, так что изменить размер выберите также размеры.

$(".node").each(function(i){ 
    $(this).resizable({alsoResize: ".my-list"+i}); 
}) 

рабочий код here

+0

Привет Кирилл! Теперь изменение размера действительно работает, поскольку оно задумано спасибо за вашу помощь здесь! Однако из-за удаления событий перетаскивания он имеет недостаток, что узлы больше не могут перемещаться. Есть ли способ поддерживать перетаскивание узлов? –

+0

ну, извините, я думаю, что у вас не может быть лучшего из обоих миров :). Может быть, кнопка или что-то добавить перетащить прослушиватели, а затем отменить ее при изменении размера. – Cyril

+0

Okay :) Итак, теперь я нашел способ удалить прослушиватель drag-list для одного узла, используя эту строку d3.select ('# Node1'). On ('. Drag', null); , Это отключает перетаскивание для Node1 и делает его изменяемым по размеру. К сожалению, я не могу принести элемент-перехватчик обратно на элемент. Я попытался использовать ** var dragCallback = d3.select ('# Node1'). Свойство ('__ onmousedown.drag') ['_']; **, а затем has3.select ('# Node1'). on ('mousedown.drag', dragCallback); но я уже получаю сообщение: Uncaught TypeError: Невозможно прочитать свойство «_» неопределенного. –

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

  • Нет связанных вопросов^_^