title: D3.js version 4 make nodes sticky
body: <p>I'm a new user of D3 version 4, and I'm having problems adding a fixed node feature to a force directed layout. I believe this was achieved in v3 by setting d.fixed to true, however I'm having issues translating this into something compatible with v4. I've tried adding simulation.fix, but can't integrate this into my existing code without fixing nodes from the start of the simulation. </p>
  
  <p>Ideally, I would like to add a double-click listener that would fix a node in place, and allow it to be positioned by a drag function, and then restore the simulation forces if double clicked again. Thank you in advance for the help.</p>
  
  <p>Here is my js:</p>
  
  <pre><code>&lt;!--load svg--&gt;
  &lt;svg width="1500" height="600"&gt;&lt;/svg&gt;
   &lt;!--begin javascript for d3 forced layout--&gt;
  &lt;script&gt;
  var svgNetwork = d3.select("svg"),
      width = +svgNetwork.attr("width"),
      height = +svgNetwork.attr("height");
  
  
  var simulation = d3.forceSimulation()
      .force("link", d3.forceLink().id(function(data1) { return data1.id; }))
      .force("charge", d3.forceManyBody().strength(-1500))
      .force("center", d3.forceCenter(width / 2, height / 2));
  
  
  
  //load  the node csv data and link csv data together - open node(open link(funtions for making chart))
  d3.csv("nodes.csv", function (error1, data1) {
      if (error1) throw error1;
      console.log(data1);
  
      d3.csv("lines.csv", function (error2, data2) {
          if (error2) throw error2;
          console.log(data2);
  
          data1.forEach(function (data1){
              data1.group = +data1.group;
          });
  
          var lower = d3.min(data1, function(data1) {return data1.group;});
          var upper = d3.max(data1, function(data1) {return data1.group;});
          var color = d3.scaleLinear()
              .domain([lower, 0, upper])
              .range(["#2E64FE", "#E6E6E6", "red"]);
  
  
          var link = svgNetwork.append("g")
              .attr("class", "links")
              .selectAll("line")
              .data(data2)
              .enter()
                  .append("line")
                  .attr("stroke-width", function(data2) { return Math.sqrt(data2.value); })
              .attr("fill", "#777")
              .attr("stroke-opacity", "0.6");
  
      var node = svgNetwork.selectAll(".node")
           .data(data1)
               .enter()
                   .append("g");
  
          var circle = node.append("circle")
              .attr("id", function(data1) {return data1.id;})
              .attr("r", function(data1) {return data1.rad;})
              .attr("fill", function(data1) { return color(data1.group); })
              .style("stroke", function(data1) { return color(data1.group); })
              .style("stroke-width", "10px")
              .style("stroke-opacity", "0.9");    
  
          var label = node.append("svg:text")
              .text(function (data1) { return data1.id; })
              .style("text-anchor", "middle")
              .style("fill", "#000000")
              .style("font-family", "Arial")
              .style("font-size", "0.8em")
              .style("font-weight", "bold");
  
     node.call(d3.drag()
            .on("start", dragstarted)
            .on("drag", dragged)
            .on("end", dragended));
  
  
    simulation
        .nodes(data1)
        .on("tick", ticked);
    simulation.force("link")
        .links(data2);
  
    function ticked() {
      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("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
  
          }
  
      });
  });
  
  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;
  }
  
  function dragended(d) {
    if (!d3.event.active) simulation.alphaTarget(0);
    d.fx = null;
    d.fy = null;
  }
  </code></pre>
  
  <p>Here is an example of my node.csv file and lines.csv file:</p>
  
  <h2>node.csv</h2>
  
  <pre><code>id  group   rad
  a   0.168316947 0.288907878
  b   -0.38499088 1.012210504
  c   -0.548386797    1.301376974
  d   -0.215565786    2.456429671
  e   -0.756094177    6.409396582
  f   -0.538867892    1.804950731
  g   -0.325232806    0.518895927
  h   0.686157994 1.011850971
  i   -0.723155438    5.853700074
  j   2.008089674 2.73207752
  k   -0.358621917    2.040722107
  l   -0.393305984    3.221637083
  m   -0.676289998    1.598250699
  n   -0.950808451    26.26021586
  o   0.134589658 0.270633823
  p   -0.521333199    6.216421369
  q   1.628300116 2.293471337
  r   0.62673 2
  s   -0.843711093    40.86067523
  </code></pre>
  
  <h2>lines.csv</h2>
  
  <pre><code>source  target  value
  b   a   20
  c   a   20
  d   a   20
  e   a   20
  f   a   20
  g   a   20
  h   a   20
  i   a   20
  j   a   20
  k   a   20
  l   a   20
  m   a   20
  n   a   20
  o   a   20
  p   a   20
  q   a   20
  r   a   20
  s   a   20
  </code></pre>