选择行

时间:2015-10-15 23:16:42

标签: javascript d3.js

这就是我目前使用的。

<!DOCTYPE HTML>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">

    <title>Git commit history</title>

</head>
<body>

<button onclick="f(data0)">Original</button>
<button onclick="f(data1)">Final</button>

    <div id="chart"></div>

<script src='http://d3js.org/d3.v3.min.js'></script>

<script>

var data1 = {"directed": true, "HEAD": "37e1d1e19f1ed57f8635ba4ba48d7a6a16ec52f6", "links": [{"source": 0, "target": 2}, {"source": 2, "target": 1}, {"source": 3, "target": 4}, {"source": 4, "target": 0}, {"source": 4, "target": 5}, {"source": 5, "target": 2}], "multigraph": false, "graph": [], "labels": ["master"], "master": "37e1d1e19f1ed57f8635ba4ba48d7a6a16ec52f6", "nodes": [{"message": "Add barn door", "id": "2b818acb7782772d0b43a0fbfd18320348c66d09", "pos": [182.04, 162.0]}, {"message": "Initial commit", "id": "5d49116ea5679a9eb21225f05dd4874b3a0b5e35", "pos": [371.04, 18.0]}, {"message": "Add animals", "id": "a21fd23c9a9742c93febff279d7f917d457c0f04", "pos": [371.04, 90.0]}, {"message": "Add chickens", "id": "37e1d1e19f1ed57f8635ba4ba48d7a6a16ec52f6", "pos": [371.04, 306.0]}, {"message": "Merge branch 'add-barn-doors'", "id": "f0f204010fe90e377f37c8e466110e49e420ac9e", "pos": [371.04, 234.0]}, {"message": "Remove cow", "id": "009d60bee58372a19e1188368ecfcc3c9ed5c2f1", "pos": [560.04, 162.0]}]}

var data0 = {"directed": true, "HEAD": "f0f204010fe90e377f37c8e466110e49e420ac9e", "links": [{"source": 0, "target": 4}, {"source": 1, "target": 0}, {"source": 1, "target": 2}, {"source": 2, "target": 4}, {"source": 4, "target": 3}], "multigraph": false, "graph": [], "labels": ["master"], "master": "f0f204010fe90e377f37c8e466110e49e420ac9e", "nodes": [{"message": "Add barn door", "id": "2b818acb7782772d0b43a0fbfd18320348c66d09", "pos": [182.04, 162.0]}, {"message": "Merge branch 'add-barn-doors'", "id": "f0f204010fe90e377f37c8e466110e49e420ac9e", "pos": [371.04, 234.0]}, {"message": "Remove cow", "id": "009d60bee58372a19e1188368ecfcc3c9ed5c2f1", "pos": [560.04, 162.0]}, {"message": "Initial commit", "id": "5d49116ea5679a9eb21225f05dd4874b3a0b5e35", "pos": [371.04, 18.0]}, {"message": "Add animals", "id": "a21fd23c9a9742c93febff279d7f917d457c0f04", "pos": [371.04, 90.0]}]}

var w = 1500,
    H = 50,
    fill = d3.scale.category20();

var h = H;

var vis = d3.select("#chart")
  .append("svg:svg");

var f = function(data) {

h = H*1.45*data.nodes.length;

    vis.attr("height", h)
    .attr("width", w);

    h = H*1.45*data.nodes.length;

        vis.attr("height", h);

    var transitiontime = 150;

var PosX = function(d, i, location) { return data.nodes[d[location]].pos[0]; };
var PosY = function(d, i, location) { return h-data.nodes[d[location]].pos[1]; };

var reverseMap = {};

    for(var i=0; i<data.nodes.length; i++){
    var p = data.nodes[i];
    var hash = p.id;
    reverseMap[hash] = p;
    };

    function poslink(d, i){ try{ return data.nodes[d.source].id + "" + data.nodes[d.target].id;} catch(err) {console.log(err); } }


var linkUpdateSelection = vis.selectAll(".link")
    .data(data.links, poslink);

    linkUpdateSelection.exit().remove();

    linkUpdateSelection
    .enter().append("line")          // attach a line
    .attr("class", "link")
    .style("stroke", "black")  // colour the line
    .attr("x1", function(d, i) {return PosX(d, i, "source");}) // x position of the first end of the line
    .attr("y1", function(d, i) {return PosY(d, i, "source");}) // y position of the first end of the line
    .attr("x2", function(d, i) {return PosX(d, i, "target");}) // x position of the second end of the line
    .attr("y2", function(d, i) {return PosY(d, i, "target");})    // y position of the second end of the line
     .style('opacity', 0);

     linkUpdateSelection
    .attr("class", "link")
    .style("stroke", "black")  // colour the line
        .transition()
        .delay(function(d,i) {return i*transitiontime})
    .attr("x1", function(d, i) {return PosX(d, i, "source");}) // x position of the first end of the line
    .attr("y1", function(d, i) {return PosY(d, i, "source");}) // y position of the first end of the line
    .attr("x2", function(d, i) {return PosX(d, i, "target");}) // x position of the second end of the line
    .attr("y2", function(d, i) {return PosY(d, i, "target");})    // y position of the second end of the line
        .style('opacity', 1);

  var nodeUpdateSelection = vis.selectAll("circle.node")
      .data(data.nodes, function(d) {return d.id});

    nodeUpdateSelection.exit().remove();

    nodeUpdateSelection.enter().append("svg:circle")
      .attr("class", "node")
      .attr("cx", function(d, i) { return d.pos[0]; })
      .attr("cy", function(d, i) { return h-d.pos[1]; })
      .attr("r", 0)
      .attr('fill', function(d, i) {if (reverseMap[d.id]==reverseMap[data['HEAD']]){return '#99FF66';} else {return 'red';}} )
      .on('mouseover', function(d,i) {
        d3.select(this).transition()
          .ease('cubic-out')
          .duration('200')
          .attr("r", 15)
      })
      .on('mouseout', function(d,i) {
        d3.select(this).transition()
          .ease('cubic-out')
          .duration('200')
          .attr("r", 10)
      });

    nodeUpdateSelection.transition()
        .delay(function(d,i) {return i*transitiontime})
        .attr("class", "node")
        .attr("cx", function(d, i) { return d.pos[0]; })
        .attr("cy", function(d, i) { return h-d.pos[1]; })
        .attr('fill', function(d, i) {if (reverseMap[d.id]==reverseMap[data['HEAD']]){return '#99FF66';} else {return 'red';}} )
        .attr("r", 10);

    var textUpdateSelection = vis.selectAll("text.message")
        .data(data.nodes, function(d) {return d.id});

    textUpdateSelection.exit().remove();

    textUpdateSelection
    .enter().append("text")
      .text(function(d) { return d.id.substring(0, 6) + " - " + d.message; })
                 .attr("x", function(d) { return 15+d.pos[0]; })
                 .attr("y", function(d) { return h-d.pos[1]+5; })
                 .attr("font-family", "sans-serif")
                 .attr("class", "message")
                 .attr("font-size", "15px")
                 .attr("fill", "blue")
                 .style('fill-opacity', 0);

    textUpdateSelection
      .text(function(d) { return d.id.substring(0, 6) + " - " + d.message; })
                 .transition()
                 .delay(function(d,i) {return i*transitiontime})
                    .style('fill-opacity', 1)
                 .attr("x", function(d) { return 15+d.pos[0]; })
                 .attr("y", function(d) { return h-d.pos[1]+5; })
                 .attr("class", "message")
                 .attr("font-family", "sans-serif")
                 .attr("font-size", "15px")
                 .attr("fill", "blue");


    var labelUpdateSelection = vis.selectAll("text.labels")
        .data(data.labels);

var labelPosX = function(d) { return reverseMap[d].pos[0]; };
var labelPosY = function(d) { return reverseMap[d].pos[1]; };

    labelUpdateSelection.exit().remove();

    labelUpdateSelection.enter().append("text")
      .text(function(d) { return d })
                    .style('fill-opacity', 0)
     .attr("x", function(d, i) { return data[d][0]- 75; })
     .attr("y", function(d, i) { return h-data[d][1] + 5; })
     .attr("class", "labels")
     .attr("font-family", "sans-serif")
     .attr("font-size", "15px");

    labelUpdateSelection
      .text(function(d) { return d })
                 .transition()
                 .delay(function(d,i) {return i*transitiontime})
                    .style('fill-opacity', 1)
     .attr("x", function(d, i) { return labelPosX(data[d]) - 50 ; })
     .attr("y", function(d, i) { return h-labelPosY(data[d]) - 25 + i*5; })
     .attr("class", "labels")
     .attr("font-family", "sans-serif")
     .attr("font-size", "15px");


    }

f(data0)
    </script>
</body>
</html>

但是,在更新期间,线条不会按预期移动。我会尝试发布正在发生的事情的截屏,以便更好地解释。我当前的实现适用于图形中的节点,但出于某种原因不适用于行。我觉得我在这里错过了一些愚蠢的东西。

完整代码超过here

编辑:

这是当前发生的screencast。我希望两个节点之间的线路保持在这两个节点之间。

编辑II:

我在上面添加了一个完整的工作示例,其中包含数据作为代码的一部分

1 个答案:

答案 0 :(得分:0)

问题是您的关键功能是引用data,它会在不同呼叫之间发生变化。链接的源节点和目标节点由索引引用,并且相同的索引指向具有不同数据的不同节点。也就是说,对于原始数据,索引0可以引用“foo”,但是对于新数据,相同的索引引用“bar”。

解决此问题的最简单方法是使用链接以一种在数据更改时不会更改的方式保存索引:

data.links.forEach(function(d) {
  d.id = data.nodes[d.source].id + "" + data.nodes[d.target].id;
});

然后您的数据匹配变为

var linkUpdateSelection = vis.selectAll("line.link")
  .data(data.links, function(d) { return d.id; });

并且更新按预期工作。完整演示here

相关问题