D3.js V4带标签和缩放的力有向图

D3.js V4带标签和缩放的力有向图,d3.js,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-c

我是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>

.连接线{
行程:#999;
笔划不透明度:0.6;
}
.节点圆{
笔画:黑色;
笔划宽度:0px;
}
.svg容器{
显示:内联块;
位置:相对位置;
宽度:100%;
垫底:100%;
垂直对齐:顶部;
溢出:隐藏;
}
.svg内容{
显示:内联块;
位置:绝对位置;
排名:0;
左:0;
}
var宽度=3000;
var高度=3000;
//创建放置力定向图的位置
var svg=d3.选择(“div#container”)
.append(“svg”)
.attr(“保存Aspectratio”、“xMinYMin满足”)
.attr(“视图框”,“0 0 3000”)
.classed(“svg内容”,真);
var color=d3.scaleOrdinal(d3.schemeCategory 20);
var半径=5;
变量节点_数据;//全球的
var links_data;//全球的
d3.json(“features\u map\u export.json”),函数(错误,数据){
nodes\u data=data.nodes
links\u data=data.links
var simulation=d3.forceSimulation()
.节点(节点\数据);
var link\u force=d3.forceLink(links\u数据)
.id(函数(d){返回d.name;});
var charge_force=d3.forceManyBody()
.兵力(-100);
变量中心力=d3力中心(宽度/2,高度/2);
模拟
.force(“冲锋队”,冲锋队)
.力(“中心力”,中心力)
.力(“链接”,链接力)
;
//添加勾号说明:
模拟。on(“滴答声”,滴答声动作);
//为缩放添加包围组
var g=svg.append(“g”)
.attr(“类”、“一切”);
//为链接画线
var link=g.append(“g”)
.attr(“类”、“链接”)
.selectAll(“行”)
.数据(链接和数据)
.enter().append(“行”)
.attr(“笔划宽度”,2)
.风格(“笔划”,颜色);
//为节点绘制圆
var节点=g.append(“g”)
.attr(“类”、“节点”)
.selectAll(“圆圈”)
.数据(节点\数据)
.输入()
.附加(“圆圈”)
.attr(“r”,5)
.style(“fill”,函数(d){返回颜色(d.group);});
node.append(“标题”)
.text(函数(d){返回d.name;});
node.append(“文本”)
.attr(“dx”,12)
.attr(“dy”,“.35em”)
.text(函数(d){return d.category});
//添加拖动功能
var drag_handler=d3.drag()
。打开(“开始”,拖动开始)
.打开(“拖动”,拖动)
.打开(“结束”,拖动至“结束”);
拖拽处理器(节点);
//添加缩放功能
var zoom_handler=d3.zoom()
.打开(“缩放”,缩放动作);
缩放处理程序(svg);
/**功能**/
//函数选择我们拥有的颜色圈
//让我们为雄性返回蓝色,为雌性返回红色
函数圈颜色(d){
返回“粉红色”;
}
//用于选择线条颜色和厚度的函数
//如果链接类型为“A”,则返回绿色
//如果链接类型为“E”,则返回红色
功能链接颜色(d){
返回“绿色”;
}
//拖动函数
//d是节点
函数拖动_开始(d){
如果(!d3.event.active)simulation.alphaTarget(0.3.restart();
d、 fx=d.x;
d、 fy=d.y;
}
//确保不能将圆拖动到框外
函数拖动(d){
d、 fx=d3.event.x;
d、 fy=d3.event.y;
}
函数拖动结束(d){
如果(!d3.event.active)simulation.alphaTarget(0);
d、 fx=null;
d、 fy=null;
}
//缩放功能
函数zoom_actions(){
g、 属性(“转换”,d3.event.transform)
}
函数操作(){
//在模拟的每个记号处更新圆位置
节点
.attr(“transform”,函数(d){return”translate(“+d.x+”,“+d.y+”));;
//更新链接位置
链接
.attr(“x1”,函数(d){返回d.source.x;})
.attr(“y1”,函数(d){返回d.source.y;})
.attr(“x2”,函数(d){返回d.target.x;})
.attr(“y2”,函数(d){返回d.target.y;});
}
});

我最近在这方面做了很多工作,请看一下plunker中的完整解决方案

这里的关键点是:

   .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中是相当明显的

希望这有帮助