【问题标题】:Dynamically resize a div when it is used as a node in a d3 force-directed graph将 div 用作 d3 力导向图中的节点时动态调整其大小
【发布时间】:2017-02-15 09:16:40
【问题描述】:

你好 Stackoverflow 社区!

所以我的问题如下:

我有一个 d3 力导向图。该图的节点是 div。 现在我希望能够使用鼠标调整这个 div 的大小。为此,我使用 jqueryui resizable()。

不幸的是,它呈现了 ui 更改(当我到达节点的边缘时,我得到了用于调整大小的 mousesymbol),但我无法调整它们的大小。我相信这是因为 d3-forcegraph 覆盖了 jqueryui 函数。我试图停止图表,以便我可以访问调整大小的功能,但这似乎不起作用。

有人知道如何使这些 div 可调整大小吗? 我创建了一个小提琴来表达我的意思: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;
}

【问题讨论】:

    标签: javascript jquery-ui d3.js


    【解决方案1】:

    第一个改变,你需要移除拖动开始和结束事件:

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

    原因:他们正在吃掉事件,所以 JQUERY 可调整大小将不起作用。

    第二次将类添加到您的选择中,以便它们是唯一的(将用于 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

    【讨论】:

    • 你好西里尔!调整大小现在确实有效,因为它是有意的,感谢您在这里的帮助!但是,由于删除了拖动事件,它具有节点不能再移动的缺点。有没有办法仍然保持节点可拖动?
    • 很抱歉,我认为您不能两全其美:)。可能是一个按钮或添加拖动侦听器的东西,然后在调整大小时将其撤消。
    • 好的 :) 所以我现在找到了一种方法来删除单个节点的拖动侦听器,方法是使用这一行 d3.select('#Node1').on('.drag', null) ; .这会禁用 Node1 的拖动并使其可调整大小。不幸的是,我无法将拖动侦听器带回元素上。我尝试使用 **var dragCallback = d3.select('#Node1').property('_onmousedown.drag')['']; ** 然后 'd3.select('#Node1').on('mousedown.drag', dragCallback);' 但我已经收到消息:Uncaught TypeError: Cannot read property '_' of undefined.
    • 我在stackoverflow.com/questions/13136355/… 看到了这个解决方案。我不知道我在尝试重新连接拖动侦听器时做错了什么。也许提议的方法不再起作用,因为我使用的是 d3 v4?
    • 使用 var listener = selection.on("mousedown.drag"); selection.on("mousedown.drag", null); // 移除 selection.on("mousedown.drag", listener); // 重新添加 现在可以移除 d3 监听器,然后调整 div 的大小,然后重新添加监听器。
    猜你喜欢
    • 2014-12-05
    • 2015-07-30
    • 2016-06-04
    • 2018-04-09
    • 1970-01-01
    • 1970-01-01
    • 2015-11-15
    • 1970-01-01
    • 2019-04-23
    相关资源
    最近更新 更多