根据json中的坐标定位节点

问题描述

我试图让有向网络的节点看起来位于页面启动时json文档中反映的坐标处。但是,实际代码重新计算了节点位置,不符合我的应用程序的要求。有什么帮助吗?

主要代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <style type="text/css">
    .node {}

    .link { 
        stroke: #999; 
        stroke-opacity: .6; 
        stroke-width: 1px; 
        }
    line {
        stroke: rgb(212,212,212);
        stroke-width: 1px;
        shape-rendering: crispEdges; 
        }
    svg { 
        box-sizing: border-box;
        border: 1px solid rgb(212,212);
        }
    </style>
    </head>
    <body>
    <svg width="960" height="600"></svg>

    <script src="https://d3js.org/d3.v4.min.js" type="text/javascript"></script>
    <script src="https://d3js.org/d3-selection-multi.v1.js"></script>

    <script type="text/javascript">

    var width = 960,height = 500,resolution = 150,r = 15;

    var colors = d3.scaleOrdinal(d3.schemeCategory10);

    var svg = d3.select("svg"),width = +svg.attr("width"),height = +svg.attr("height"),node,link;

    svg.selectAll('.vertical')
    .data(d3.range(1,width / resolution))
    .enter().append('line')
    .attr('class','vertical')
    .attr('x1',function(d) { return d * resolution; })
    .attr('y1',0)
    .attr('x2',function(d) { return d * resolution; })
    .attr('y2',height);

    svg.selectAll('.horizontal')
    .data(d3.range(1,height / resolution))
    .enter().append('line')
    .attr('class','horizontal')
    .attr('x1',0)
    .attr('y1',function(d) { return d * resolution; })
     .attr('x2',width)
    .attr('y2',function(d) { return d * resolution; });

    svg.append('defs').append('marker')
    .attrs({'id':'arrowhead','viewBox':'-0 -5 10 10','refX':13,'refY':0,'orient':'auto','markerWidth':13,'markerHeight':13,'xoverflow':'visible'})
    .append('svg:path')
    .attr('d','M 0,-5 L 10,0 L 0,5')
    .attr('fill','#999')
    .style('stroke','none');

    var simulation = d3.forceSimulation()
    .force("link",d3.forceLink().id(function (d) {return d.id;}).distance(150).strength(1))
    //.force("charge",d3.forceManyBody())
    //.force("center",d3.forceCenter(width / 2,height / 2));

    d3.json("graph.json",function (error,graph) {
    if (error) throw error;
    update(graph.links,graph.nodes);
    })

    function update(links,nodes) {
    link = svg.selectAll(".link")
        .data(links)
        .enter()
        .append("line")
        .attr("class","link")
        .attr('marker-end','url(#arrowhead)')

    link.append("title")
        .text(function (d) {return d.type;});

    edgepaths = svg.selectAll(".edgepath")
        .data(links)
        .enter()
        .append('path')
        .attrs({
            'class': 'edgepath','fill-opacity': 0,'stroke-opacity': 0,'id': function (d,i) {return 'edgepath' + d.type}
        })
        .style("pointer-events","none");

    edgelabels = svg.selectAll(".edgelabel")
        .data(links)
        .enter()
        .append('text')
        .style("pointer-events","none")
        .attrs({
            'class': 'edgelabel',i) {return 'edgelabel' + i},'font-size': 15,'fill': '#000'
        });

    edgelabels.append('textPath')
        .attr('xlink:href',function (d,i) {return '#edgepath' + i})
        .style("text-anchor","middle")
        .style("pointer-events","none")
        .attr("startOffset","50%")
        .text(function (d) {return d.type});

    node = svg.selectAll(".node")
        .data(nodes)
        .enter()
        .append("g")
        .attr("class","node")
        .attr('cx',function(d) { return d.x; })
        .attr('cy',function(d) { return d.y; })
        .call(d3.drag()
                .on("start",dragstarted)
                .on("drag",dragged)
                //.on("end",dragended)
        );

    node.append("circle")
        .attr("r",15)
        .style("fill",i) {return colors(i);})

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

    node.append("text")
        .attr("dy",-3)
        .text(function (d) {return d.name+":"+d.social;});

    simulation
        .nodes(nodes)
        .on("tick",ticked);

    simulation.force("link")
        .links(links);
    }

    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 + ")";});

    edgepaths.attr('d',function (d) {
        return 'M ' + d.source.x + ' ' + d.source.y + ' L ' + d.target.x + ' ' + d.target.y;
    });
    }

    function dragstarted(d) {
    if (!d3.event.active) simulation.alphaTarget(1.0).restart()
    d.fx = d.x;
    d.fy = d.y;
    }

    function dragged(d) {
    d.fx = d3.event.x;
    d.fy = d3.event.y;

    gridX = round(Math.max(r,Math.min(width - r,d.fx)),resolution);
    gridY = round(Math.max(r,Math.min(height - r,d.fy)),resolution);

    d3.select(this).attr('cx',d.fx = gridX).attr('cy',d.fy = gridY);


    }

    function round(p,n) {
    return p % n < n / 2 ? p - (p % n) : p + n - (p % n);
    }

    </script>

    </body>
    </html>

这里我附上承载定向的json文档的数据 图数据:

    {
     "nodes": [
    {
      "name": "1","label": "1","social": "I","id": 1,"x": 150,"y": 450
    },{
      "name": "2","label": "2","social": "G","x": 300,"y": 150
    },{
      "name": "3","label": "3","social": "T","x": 450,"y": 300
    }
    ],"links": [
    {
      "source": 1,"target": 2,"type": "N:1"
    },{
      "source": 2,"target": 3,"type": "1:N"
    }
    ]
    }

解决方法

此代码不起作用:

node = svg.selectAll(".node")
  .data(nodes)
  .enter()
  .append("g")
  .attr("class","node")
  .attr('cx',function(d) { return d.x; })
  .attr('cy',function(d) { return d.y; })
  ...

替换为:

node = svg.selectAll(".node")
  .data(nodes)
  .enter()
  .append('g')
  .classed('node',true)
  .attr('transform',d => `translate(${d.x},${d.y})`)
  ...

元素没有 cxcy 属性,而是使用变换。此外,d3 classed 例程比 attr('class') 更有用。

UPD:新创建的链接缺少初始坐标:

link = svg.selectAll(".link")
  .data(links)
  .enter()
  .append("line")
  .classed("link",true)
  .attr('marker-end','url(#arrowhead)')
  .attr("x1",d => d.source.x)
  .attr("x2",d => d.target.x)
  .attr("y1",d => d.source.y)
  .attr("y1",d => d.target.y)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...