2015-05-16 25 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); 

這樣,我所有的固定節點不動,除非我拖累他們。