D3.js V4强制定向图形标签加变焦

时间:2017-06-14 23:16:43

标签: d3.js

我是D3的新手,我似乎找不到在D3.js v4强制导向图上同时实现节点标签和缩放/平移的方法。我的代码如下。

非常感谢任何帮助

<!DOCTYPE html>
<meta charset="utf-8">
<style>

.links line {
  stroke: #999;
  stroke-opacity: 0.6;
}

.nodes circle {
  stroke: black ;
  stroke-width: 0px;
}

.svg-container {
    display: inline-block;
    position: relative;
    width: 100%;
    padding-bottom: 100%;
    vertical-align: top;
    overflow: hidden;
}
.svg-content {
    display: inline-block;
    position: absolute;
    top: 0;
    left: 0;
}


</style>

<div id="container" class="svg-container">
</div>



<!--<svg viewBox="0 0 300 300"></svg>-->

<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

var width = 3000;
var height = 3000;

//create somewhere to put the force directed graph
var svg = d3.select("div#container")
  .append("svg")
  .attr("preserveAspectRatio", "xMinYMin meet")
  .attr("viewBox", "0 0 3000 3000")
  .classed("svg-content", true);

var color = d3.scaleOrdinal(d3.schemeCategory20);

var radius = 5;
var nodes_data; // global
var links_data; // global


d3.json("features_map_export.json", function(error, data) {
      nodes_data = data.nodes
      links_data = data.links



    var simulation = d3.forceSimulation()
                        .nodes(nodes_data);

    var link_force =  d3.forceLink(links_data)
                            .id(function(d) { return d.name; });

    var charge_force = d3.forceManyBody()
        .strength(-100);

    var center_force = d3.forceCenter(width / 2, height / 2);

    simulation
        .force("charge_force", charge_force)
        .force("center_force", center_force)
        .force("links",link_force)
     ;


    //add tick instructions:
    simulation.on("tick", tickActions );

    //add encompassing group for the zoom
    var g = svg.append("g")
        .attr("class", "everything");

    //draw lines for the links
    var link = g.append("g")
          .attr("class", "links")
        .selectAll("line")
        .data(links_data)
        .enter().append("line")
          .attr("stroke-width", 2)
          .style("stroke", linkColour);

    //draw circles for the nodes
    var node = g.append("g")
            .attr("class", "nodes")
            .selectAll("circle")
            .data(nodes_data)
            .enter()
            .append("circle")
            .attr("r", 5)
            .style("fill", function(d) { return color(d.group); });

    node.append("title")
      .text(function(d) { return d.name; });

    node.append("text")
      .attr("dx", 12)
      .attr("dy", ".35em")
      .text(function(d) { return d.category });

    //add drag capabilities
    var drag_handler = d3.drag()
        .on("start", drag_start)
        .on("drag", drag_drag)
        .on("end", drag_end);

    drag_handler(node);


    //add zoom capabilities
    var zoom_handler = d3.zoom()
        .on("zoom", zoom_actions);

    zoom_handler(svg);

    /** Functions **/

    //Function to choose what color circle we have
    //Let's return blue for males and red for females
    function circleColour(d){
        return "pink";
    }

    //Function to choose the line colour and thickness
    //If the link type is "A" return green
    //If the link type is "E" return red
    function linkColour(d){
        return "green";
    }

    //Drag functions
    //d is the node
    function drag_start(d) {
     if (!d3.event.active) simulation.alphaTarget(0.3).restart();
        d.fx = d.x;
        d.fy = d.y;
    }

    //make sure you can't drag the circle outside the box
    function drag_drag(d) {
      d.fx = d3.event.x;
      d.fy = d3.event.y;
    }

    function drag_end(d) {
      if (!d3.event.active) simulation.alphaTarget(0);
      d.fx = null;
      d.fy = null;
    }

    //Zoom functions
    function zoom_actions(){
        g.attr("transform", d3.event.transform)
    }

    function tickActions() {
        //update circle positions each tick of the simulation
        node
            <!--.attr("cx", function(d) { return d.x; })-->
            <!--.attr("cy", function(d) { return d.y; })-->
            .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });;

        //update link positions
        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; });


    }

});
</script>

1 个答案:

答案 0 :(得分:3)

我最近在这个领域做了很多工作,看看这个完整的解决方案... ...

http://plnkr.co/edit/ZSmvH05nnAD6cYZb0EM4?p=preview

这里的关键点是:

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

然后只包括锅炉板拖动功能:

//Used to drag the graph round the screen
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;
}

对于缩放,这只是将缩放处理程序附加到顶级svg容器的情况...有关详细信息,请参阅Plunker。

svg.call(zoom_handler)
.call(zoom_handler.transform, d3.zoomIdentity.scale(1,1))
;

可以通过更改比例值来设置初始缩放:

.call(zoom_handler.transform, d3.zoomIdentity.scale(0.5,0.5))

将是一半大小。

至于贴上你的标签,这应该是从Plunker中显而易见的。

希望这有帮助