根据json中的坐标定位节点 [英] Locating the nodes according to the coordinates in the json

查看:99
本文介绍了根据json中的坐标定位节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to make the nodes of the directed network appear to be located at the coordinates reflected in the json document when the page is started. However, the actual code recalculates the node positions, which does not fit the requirements of my application . Any help?

主要代码

    <!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, 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',
            'id': function (d, 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", function (d, 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文档的数据图形数据:

Here I attach the data of the json document that hosts the directed graph data:

    {
     "nodes": [
    {
      "name": "1",
      "label": "1",
      "social": "I",
      "id": 1,
      "x": 150, 
      "y": 450
    },
    {
      "name": "2",
      "label": "2",
      "social": "G",
      "id": 1,
      "x": 300, 
      "y": 150
    },
    {
      "name": "3",
      "label": "3",
      "social": "T",
      "id": 1,
      "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})`)
  ...

< g> 元素没有 cx cy 属性,它使用了transform.此外,d3 分类例程比 attr('class')更为有用.

<g> element does not have cx and cy attributes, it uses transform instead. Also, d3 classed routine is more usable than attr('class').

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

UPD: The newly created links are missing their initial coordinates:

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)

这篇关于根据json中的坐标定位节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆