2015-05-16 45 views
0

我的问题如下:虽然我为我的节点设置了fixed : true,但只有第一个(从json文件加载)被修复。新的(由用户创建的)不是固定的,即使使用浏览器的开发者工具,我们也可以看到fixed="true"属性。 redraw()函数中缺少一些东西吗?我应该使用tick()吗?我在这个问题上奋斗了一个星期,我不知道了。d3js为什么我的固定节点在移动?

这是我的整个代码(其中初始节点确实是固定的),但我也提出了一个jsfiddle(其中初始节点也不固定)。

// Plan 
var width = 960, 
    height = 500; 

// Orange selected element 
var selected_node = null, 
    selected_link = null; 

// Element we clicked on it 
var mouseclick_node = null, 
    mouseclick_link = null; 

// To detect click or double click. 
var clickedOnce = false, 
    timer; 

// Useful function to compute the size of an element. 
d3.selection.prototype.size = function() { 
    var n = 0; 
    this.each(function() { ++n; }); 
    return n; 
}; 


var svg = d3.select("body") 
    .append("svg") 
    .attr("width", width) 
    .attr("height", height) 
    .attr("pointer-events", "all"); 

var visual = svg 
    .append('svg:g') 
    .append('svg:g') 
     .on("mousemove", mousemove) 
     .on("click", click); 

// ajoute une balise rect nested dans g, ave préfix svg 
visual.append('svg:rect') 
    .attr('width', width) 
    .attr('height', height) 
    .attr('fill', 'white'); 

var force = d3.layout.force() 
    .size([width, height]) 
    .charge(-400) 
    .on("tick", tick); 

// Future link 
var drag_line = visual.append("line") 
    .attr("class", "drag_line") 
    .attr("x1", 0) 
    .attr("y1", 0) 
    .attr("x2", 0) 
    .attr("y2", 0); 

// get layout properties 
var nodes = force.nodes(), 
    links = force.links(); 
var node = visual.selectAll(".node"), 
    link = visual.selectAll(".link"); 

// Allows the drag actions 
var drag = force.drag(); 

// Read the json file and creates the links and the nodes 
    d3.json("graph_empty.json", function(error, graph) { 

    if (error) console.log("error: " + error); 

    nodes = graph.nodes; 
    links = graph.links; 

    // To redraw after loading nodes and links 
    redraw(); 
}); 


// Add properties to links and nodes 
function tick() { 
    link.attr("x1", function (d) { 
     return d.source.x; 
    }) 
     .attr("y1", function (d) { 
     return d.source.y; 
    }) 
     .attr("x2", function (d) { 
     return d.target.x; 
    }) 
     .attr("y2", function (d) { 
     return d.target.y; 
    }); 

    node.attr("cx", function (d) { 
     return d.x; 
    }) 
     .attr("cy", function (d) { 
     return d.y; 
    }); 
} 


function mousemove() { 
    var point = d3.mouse(this), p = {x: point[0], y: point[1]}; 

    if (selected_node) { 
    drag_line 
     .attr("x1", selected_node.x) 
     .attr("y1", selected_node.y) 
     .attr("x2", p.x) 
     .attr("y2", p.y); 
    } 
} 

function click() { 
    var point = d3.mouse(this), p = {x: point[0], y: point[1]}; 

    // if already clicked once 
    if (clickedOnce) { 
     run_on_double_click(); 
    } 
    // otherwise 
    else { 
    timer = setTimeout(function() { 
     run_on_simple_click(point); 
    }, 150); 
    clickedOnce = true; 
    } 
} 

function run_on_simple_click(p) { 
    console.log("[run_on_simple_click]"); 
    clickedOnce = false; 

    if (!mouseclick_node && selected_node) { 

    // add a new node 
    point = {x: p[0], y: p[1]}; 
    nodes.push(point); 

    // add link to mousedown node 
    links.push({source: selected_node, target: point}); 

    // select the new node 
    selected_node = point; 
    selected_link = null; 

    // update the drag line 
    drag_line 
     .attr("x1", selected_node.x) 
     .attr("y1", selected_node.y) 
     .attr("x2", p.x) 
     .attr("y2", p.y); 

    redraw(); 
    } 
} 

function run_on_double_click() { 
    clickedOnce = false; 
    clearTimeout(timer); 
    console.log("[run_on_double_click]"); 
} 

function resetMouseVars() { 
    console.log("[resetMouseVars]"); 
    mouseclick_node = null; 
    mouseclick_link = null; 
} 

function redraw() { 
    console.log("[redraw start]"); 

    force 
     .nodes(nodes) 
     .links(links) 

    link = link.data(links); 

    link.enter().append("line") 
    .attr("class", "link") 
    .on("click", function(d) { 
     // double click: 
     if (clickedOnce_On) { 
      clickedOnce_On = false; 
      clearTimeout(timer); 

      mouseclick_link = d; 
      if (!selected_link) 
       selected_link = mouseclick_link; 
      else if (mouseclick_link == selected_link) 
       selected_link = null; 
      else if (mouseclick_link == selected_link) { 
       selected_link = null; 
       selected_link = mouseclick_link; 
      } 
      selected_node = null; 
      resetMouseVars(); 
      redraw(); 
     } 
     // single click: 
     else { 
      timer = setTimeout(function() { 
      // to do... create a new node between ! 
      }, 250); 
      clickedOnce_On = true; 
     } 
    }); 

    link.exit().remove(); 

    link.classed("link_selected", function(d) { 
        return d === selected_link; 
       }); 

    node = node.data(nodes); 

    var clickedOnce_On = false; 
    node.enter().append("circle") 
    .attr("class", "node") 
    .attr("r", 6) 
    .attr("fixed", true) 
    .call(drag) 
    .on("click", function(d) { 
     mouseclick_node = d; 

     // double click: 
     if (clickedOnce_On) { 
      clickedOnce_On = false; 
      clearTimeout(timer); 

      if (!selected_node) 
       selected_node = mouseclick_node; 
      else if (mouseclick_node == selected_node) 
       selected_node = null; 
      else if (mouseclick_node == selected_node) { 
       selected_node = null; 
       selected_node = mouseclick_node; 
      } 
      selected_link = null; 
      resetMouseVars(); 
      redraw(); 
     } 
     // single click: 
     else { 
      timer = setTimeout(function() { 
      // close the surface if 
      if ((selected_node) && (mouseclick_node) && (selected_node != mouseclick_node)) { 
       console.log("mouseclick_node: "+ mouseclick_node); 
       // Here: count the number of links for each node 
       // and find the node with only one link. 
       // If this node == mouseclick_node, 
       // we add a new link between it and the selected_node. 
       resetMouseVars(); 
       redraw(); 
      } 
      }, 250); 
      clickedOnce_On = true; 
     } 
    }); 

    node.exit().transition() 
    .attr("r", 0) 
    .remove(); 

    node.classed("node_selected", function(d) { 
        return d === selected_node; 
       }); 
    force 
     .start() 
     .tick(); 

    console.log("[redraw end]"); 
} 

非常感谢您提前,任何建议/意见/解决方案!

回答

0

最后,我找到了一个解决办法:我设置force像这样的属性:

var force = d3.layout.force() 
    .size([width, height]) 
    .charge(0) 
    .gravity(0) 
    .linkStrength(0) 
    .friction(0) 
    .on("tick", tick); 

这样,我所有的固定节点不动,除非我拖累他们。