0

我遇到了位于此处的以下示例。

它基于这个问题

我注意到的问题是它匹配第一个匹配节点并停止。这些关系基于每个条目的第一个匹配节点,而不是所有匹配节点。

我已经修改了代码,但我似乎无法弄清楚为什么图表不能正确呈现。

执行此操作的代码部分位于下面的第 64 行到第 128 行之间。完整的源代码在这里:http ://bl.ocks.org/hijonathan/raw/5793014/664407f1855a61250b30458b583fb59635bf3157/script.js

该脚本使用 underscore.js,我认为更正应该是使用 _.filter 而不是 _.find。关于修改此代码以包含所有关系的任何建议,而不是匹配第一个并停止?

可以在此处找到输出的实时示例。

var width = document.width,
    height = document.height,
    nodeRadius = 20,
    subNodeRadius = nodeRadius / 2,
    k = Math.sqrt(12 / (width * height));

var color = d3.scale.category20();

var force = d3.layout.force()
    .linkDistance(function(d) {
      if (d.type && d.type === 'property') {
        return 10;
      }
      else {
        return 100;
      }
    })
    .charge(-10 / k)
    .gravity(100 * k)
    .size([width, height])

var svg = d3.select("body").append("svg:svg")
    .attr("width", width)
    .attr("height", height)
    .attr("pointer-events", "all")
    .append('svg:g')
      .call(d3.behavior.zoom().on("zoom", redraw))
    .append('svg:g');

svg.append('svg:rect')
    .attr('width', width)
    .attr('height', height)
    .attr('fill', 'white');

function redraw() {
  console.log("here", d3.event.translate, d3.event.scale);
  svg.attr("transform",
      "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")");
}

d3.json("categories.json", function(error, graph) {
  // Break out property nodes
  var people = _.where(graph.nodes, {type: 'person'}),
      nodes = people;

  _.each(people, function(p) {
    _.each(p, function(prop, _k) {
      if (_k !== 'name' && _k !== 'Name' && _k !== 'id' && _k !== 'type') {
        nodes.push({
          target: p.id,
          type: 'property',
          name: _k,
          value: prop
        });
      }
    });
  });

  force.nodes(nodes);

  // Dynamically build links based on shared attributes
  var links = [];
  var _nodes = nodes.slice();  // copy
  _.each(nodes, function(n, i) {
    if (n.type === "person") {
      _nodes.shift();
      var t = i,
          matchKey,
          matchValue;
          //console.log(n);
      for (var key in n) {
        //console.log(n[key]+"THAT");
        if (key === 'type' || key === 'target') {
          continue;
        }
        var val = n[key];
        //console.log(val + "THIS");
        //should likely use _.filter()  as opposed to _.find... 
        t = _.filter(_nodes, function(_n) {

          //console.log(val);
          return _n[key] === val;
        });

        if (t) {
          //matchKey = key;
          //matchValue = val;
          //break;
        }
      }

      console.log(t);

        _.each(t, function(tv,tk) {//ITERATES OVER OBJECT COLLECTION

            for(var tk2 in tv){ //ITERATES OVER EACH KEY VAL PAIR IN OBJECT.
                if(tk2 ==='type' || tk2 ==='Likes Food'){
                    continue;
                }
                var val2 = tv[tk2];

                at = _.find(t, function(_at){
                    return _at[tk2] === val2;
                });
                //console.log(at+"THIS IS AT");
                if(at){

                    //console.log(tk2+":"+tv[tk2]);
                    var matchkey2 = tk2; 
                    var matchval2 = val2;
                    console.log(matchkey2+":"+matchval2);
                    var uniqat = _.clone(at);
                    delete uniqat[matchkey2];
                    //delete uniqat.name;
                    //delete uniqat['Name'];

                      links.push(_.extend({
          source: tk,
          target: (at && at.id) || tk,
          matchKey: matchkey2,
          matchValue: matchval2
        }, {props: uniqat}));

                }
            }


        });






    }
    else {
      links.push(_.extend(n, {
        source: i
      }));
    }

  });

  force.links(links);
  force.start();

  var link = svg.selectAll(".link")
      .data(links)
    .enter().append("g")
      .attr('class', function(d) {
        if (d.props) {
          return 'person link';
        }
        else return 'property link';
      });

  var line = link.append('line')
      .style("stroke-width", 1);

  var matchCirlce = svg.selectAll('.link.person')
      .append('circle')
        .attr('r', subNodeRadius)
        .style('fill', '#000');

  var text = svg.selectAll('.link.person')
      .append("text")
        .attr('dy', '.35em')
        .attr('text-anchor', 'middle')
        .text(function(d) {
          if (d.matchValue === true || d.matchValue === false) {
            return d.matchKey;
          }
          else {
            return d.matchKey+ ": " + d.matchValue;
          }
        });

  var node = svg.selectAll(".node")
      .data(nodes)
    .enter()
      .append('g')
      .attr("class", function(d) {
        if (d.type && d.type === 'person') {
          return 'node person'
        }
        else {
          return 'node property';
        }
      })
      .call(force.drag);

  var circle = node.append("circle")
      .attr("r", function(d) {
        if (d.type && d.type === 'person') {
          return nodeRadius;
        }
        else {
          return subNodeRadius;
        }
      })
      .style('fill', function(d) {
        if (d.type && d.type === 'person') {
          return color(d.id);
        }
        else {
          return '#eee'
        }
      });

  node.append("text")
      .attr('dy', '.35em')
      .attr('text-anchor', 'middle')
      .text(function(d) {
        if (d.type && d.type === 'person') {
          return d.name;
        }
        else {
          if (d.value === true || d.value === false) {
            return d.name;
          }
          else return d.value;
        }
      });

  force.on("tick", function() {

    node.attr("transform", function(d) {
      return "translate(" + d.x + "," + d.y + ")";
    });

    line.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; });

    text.attr("transform", translateBetween);
    matchCirlce.attr("transform", translateBetween);

  });

});

function translateBetween(d) {
  var x1 = d.source.x;
  var y1 = d.source.y;
  var x2 = d.target.x;
  var y2 = d.target.y;
  return "translate(" + (x1 + x2) / 2 + "," + (y1 + y2) / 2 + ")";
}
4

0 回答 0