具有可拖动节点的D3布局

时间:2017-05-17 12:08:52

标签: d3.js

我创建了一个强制布局图。它工作正常。

现在我需要使块可拖动,这样即使在拖动块之后它也不会影响其他块,如this示例所示。

这是我试过的:

    @{  var codcur = "";
        var descripcion = "";
        var horas = "";
        var tutor = "";
        int pos = 0;  

        if(IsPost) {
            pos = Convert.ToInt32(Session["position"]);
        }
        else {
            pos = 0;
        }

        using(PracticaRazor2.ModeloOcupacional Contexto = new PracticaRazor2.ModeloOcupacional()) {
            var registro = (from cur in Contexto.CURSOS orderby cur.COD_CUR select cur).Skip(pos).First();
            codcur = registro.COD_CUR;
            descripcion = registro.DESCRIPCION;
            horas = registro.HORAS.ToString();
            tutor = registro.TUTOR;
        }





        <h1>Mantenimiento cursos</h1>
        <form action="~/Cursos.cshtml" method="post">
            <label>Código curso:</label>
            <input type="text" name="cod_cur" id="cod_cur" value="@codcur" /><br />
            <label>Descripción:</label>
            <input type="text" name="descripcion" id="descripcion" value="@descripcion" /><br />
            <label>Horas:</label>
            <input type="text" name="horas" id="horas" value="@horas" /><br />
            <label>Tutor:</label>
            <input type="text" name="tutor" id="tutor" value="@tutor" /><br />

            <br /><br />

            <input type="submit" name="first" id="first" value="|<" onclick="@first(pos)"/>
            <input type="submit" name="prev" id="prev" value="<<" onclick="@prev(pos)"/>
            <input type="submit" name="next" id="next" value=">>" onclick="@next(pos)"/>
            <input type="submit" name="last" id="last" value=">|" />
            <input type="submit" name="borra" id="borra" value="Borrar" />
            <input type="submit" name="Modifica" id="mod" value="Modifica" />
            <input type="submit" name="Nuevo" id="new" value="Nuevo" />



           </form>
        @functions{ 
        int next(int pos) {
                if(IsPost) {
                    pos++;
                    Session["position"] = pos.ToString();
                }
                return pos;
            }

            int prev(int pos) {
                if(IsPost) {
                    pos--;
                    Session["position"] = pos.ToString();
                }
                return pos;
            }

            int first(int pos) {
                if(IsPost) {
                    pos = 0;
                    Session["position"] = pos.ToString();
                }
                return pos;
            }
        }
    }
</body>

links.json文件中的数据是

    d3.json("links.json", function(error, links) {

    var nodes = {};

    // Compute the distinct nodes from the links.
    links.forEach(function(link) {
      link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
      link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});

    });

    var width = 1000,
        height = 700;

    var force = d3.layout.force()
        .nodes(d3.values(nodes))
        .links(links)
        .gravity(0.01) 
        .size([width, height])
        .linkDistance(200)
        .charge(-600)
        .on("tick", tick)
        .start();

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

    // Per-type markers, as they don't inherit styles.
    svg.append("defs").selectAll("marker")
        .data(["forward","back"]) //use .data(["forward","back","front"]) for different types of data
      .enter().append("marker")
        .attr("id", function(d) { return d; })
        .attr("viewBox", "0 -5 10 10")
        .attr("refX", 100)
        .attr("refY", 1.5)
        .attr("markerWidth", 6)
        .attr("markerHeight", 6)
        .attr("orient", "auto")
      .append("path")
        .attr("d", "M0,-4L10,0L0,5");

    var path = svg.append("g").selectAll("path")
        .data(force.links())
      .enter().append("path")
        .attr("class", function(d) { return "link " + d.type; })
        .attr("marker-end", function(d) { return "url(#" + d.type + ")"; });



    var rect = svg.append("g").selectAll("rect")
        .data(force.nodes())
      .enter().append("rect")
        .attr("x", -20)
        .attr("y", -20)
        .attr("width", function(d) { return (d.weight*40);  })
        .attr("height", function(d) { return (d.weight*20); })
        .call(force.drag).on("mouseover", fade(.1))
        .on("mouseout", fade(1));;

    force.drag().on('drag', fade(.1));

    var text = svg.append("g").selectAll("text")
        .data(force.nodes())
      .enter().append("text")
        .attr("x", 0)
        .attr("y", ".41em")
        .text(function(d) { return d.name; });

    // Use elliptical arc path segments to doubly-encode directionality.
    function tick() {
     rect.attr("transform", transform);
      path.attr("d", linkLine);

      text.attr("transform", transform); 
    }

    function transform(d) {
      return "translate(" + d.x + "," + d.y + ")";
    }
    });
    </script>
    </body>
    </html>

是否存在任何方法,即使我在图表中拖动某个节点,我也不会在其他节点中进行任何移动?

是否有任何单独的方法可以实现这一目标?

1 个答案:

答案 0 :(得分:1)

当强制模拟停止时,为每个节点设置属性fixedtrue

force.on('end', function(d) {
    links.forEach(function(l) {
      l.source.fixed = true;
      l.target.fixed = true;
    })
  });

var links = [{
    "source": "Delhi",
    "target": "Mangalore",
    "type": "forward"
  },
  {
    "source": "Mangalore",
    "target": "Delhi",
    "type": "back"
  },
  {
    "source": "Delhi",
    "target": "Yashvanthpur",
    "type": "back"
  },
  {
    "source": "Mangalore",
    "target": "Rome",
    "type": "forward"
  },
  {
    "source": "Delhi",
    "target": "Mysore",
    "type": "forward"
  },

  {
    "source": "Chandigarh",
    "target": "Vellore",
    "type": "forward"
  },
  {
    "source": "Chandigarh",
    "target": "Mangalore",
    "type": "forward"
  },
  {
    "source": "Delhi",
    "target": "Nagpur",
    "type": "forward"
  }

];
var nodes = {};

// Compute the distinct nodes from the links.
links.forEach(function(link) {
  link.source = nodes[link.source] || (nodes[link.source] = {
    name: link.source
  });
  link.target = nodes[link.target] || (nodes[link.target] = {
    name: link.target
  });

});

var width = 1000,
  height = 700;

var force = d3.layout.force()
  .nodes(d3.values(nodes))
  .links(links)
  .gravity(0.01)
  .size([width, height])
  .linkDistance(200)
  .charge(-600)
  .on("tick", tick)
  .start()
  
force.on('end', function(d) {
    links.forEach(function(l) {
      l.source.fixed = true;
      l.target.fixed = true;
    })
  });

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

// Per-type markers, as they don't inherit styles.
svg.append("defs").selectAll("marker")
  .data(["forward", "back"]) //use .data(["forward","back","front"]) for different types of data
  .enter().append("marker")
  .attr("id", function(d) {
    return d;
  })
  .attr("viewBox", "0 -5 10 10")
  .attr("refX", 100)
  .attr("refY", 1.5)
  .attr("markerWidth", 6)
  .attr("markerHeight", 6)
  .attr("orient", "auto")
  .append("path")
  .attr("d", "M0,-4L10,0L0,5");

var path = svg.append("g").selectAll("path")
  .data(force.links())
  .enter().append("path")
  .attr("class", function(d) {
    return "link " + d.type;
  })
  .attr("marker-end", function(d) {
    return "url(#" + d.type + ")";
  });



var rect = svg.append("g").selectAll("rect")
  .data(force.nodes())
  .enter().append("rect")
  .attr("x", -20)
  .attr("y", -20)
  .attr("width", function(d) {
    return (d.weight * 40);
  })
  .attr("height", function(d) {
    return (d.weight * 20);
  })
  .call(force.drag).on("mouseover", fade(.1))
  .on("mouseout", fade(1));;

force.drag().on('drag', fade(.1));

var text = svg.append("g").selectAll("text")
  .data(force.nodes())
  .enter().append("text")
  .attr("text-anchor", "middle")
  .attr("x", function(d){ return -20+(d.weight * 20) })
  .attr("y", function(d){ return -20+(d.weight * 20)/2 })
  .text(function(d) {
    return d.name;
  });

// Use elliptical arc path segments to doubly-encode directionality.
function tick() {
  rect.attr("transform", transform);
  path.attr("d", linkLine);

  text.attr("transform", transform);
}

var linkedByIndex = {};

links.forEach(function(d) {
  linkedByIndex[d.source.index + "," + d.target.index] = 1;
});

function isConnected(a, b) {
  return linkedByIndex[a.index + "," + b.index] ||
    linkedByIndex[b.index + "," + a.index] ||
    a.index == b.index;
};

function linkLine(d) {
  var dx = d.target.x - d.source.x,
    dy = d.target.y - d.source.y;

  return "M" + d.source.x + "," + d.source.y + "L" + d.target.x + "," + d.target.y;
}

function transform(d) {
  return "translate(" + d.x + "," + d.y + ")";
}

// For fade-in and fade-out effect
function fade(opacity) {
  return function(d) {
    rect.style("stroke-opacity", function(o) {
      thisOpacity = isConnected(d, o) ? 1 : opacity;
      this.setAttribute('fill-opacity', thisOpacity);
      return thisOpacity;
    });

    rect.style("stroke-opacity", opacity)
      .style("stroke-opacity", function(o) {
        return o.source === d || o.target === d ? 1 : opacity;
      });
  };
};
.link {
  fill: none;
  stroke: #666;
  stroke-width: 2px;
}

#forward {
  fill: green;
}

#back {
  fill: red;
}

<!-- #back {
  fill: green;
}

-->.link.forward {
  stroke: green;
}

.link.back {
  stroke: green;
}

rect {
  fill: #a5b0ed;
  stroke: #333;
  stroke-width: 2px;
}

text {
  font: 10px sans-serif;
  pointer-events: none;
  text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>