带有多个链接的D3力导向图,淡入淡出

时间:2017-11-17 16:26:32

标签: d3.js directed-graph

http://jsfiddle.net/damianpadden/a2QpA/397/

尝试为此d3力导向图添加不透明度但失败。有人能指出我正确的方向

当我选择我希望它的其他节点未连接到淡出的节点时。

如果可能,可以为标签和值添加过滤器

这是一个新手问题,所以要善良。我真的很喜欢这个,如果我只能按照我的想法让这部分工作,那将会很有用。

感谢下面的代码

 var data = {
  edges: [{
    source: {
      id: 0,
      label: "from"
    },
    target: {
      id: 1,
      label: "to"
    },
    value: "after you"
  }, {
    source: {
      id: 0,
      label: "from"
    },
    target: {
      id: 1,
      label: "to"
    },
    value: "follow my lead"
  }, {
    source: {
      id: 0,
      label: "from"
    },
    target: {
      id: 1,
      label: "to"
    },
    value: "over this way"
  },

  {
    source: {
      id: 2,
      label: "outside"
    },
    target: {
      id: 3,
      label: "lonely"
    },value:"helloooooo"
    }

  ]
};

function myGraph() {
  this.addNode = function(n) {
    if (!findNode(n.id)) {
      nodes.push({
        "id": n.id,
        "label": n.label
      });
      update();
    }
  };

  this.addLink = function(source, target, value) {
    links.push({
      "source": findNode(source.id),
      "target": findNode(target.id),
      "value": value
    });
    update();
  };

  this.initialize = function() {
    data.edges.forEach(function(d) {
      graph.addNode(d.source);
      graph.addNode(d.target);
      graph.addLink(d.source, d.target, d.value);
    });
  };

  var findNode = function(nodeId) {
    for (var i in nodes) {
      if (nodes[i].id === nodeId) {
        return nodes[i];
      }
    };
  };

  var countSiblingLinks = function(source, target) {
    var count = 0;
    for (var i = 0; i < links.length; ++i) {
      if ((links[i].source.id == source.id && links[i].target.id == target.id) || (links[i].source.id == target.id && links[i].target.id == source.id))
        count++;
    };
    return count;
  };

  var getSiblingLinks = function(source, target) {
    var siblings = [];
    for (var i = 0; i < links.length; ++i) {
      if ((links[i].source.id == source.id && links[i].target.id == target.id) || (links[i].source.id == target.id && links[i].target.id == source.id))
        siblings.push(links[i].value);
    };
    return siblings;
  };

  var w = window.innerWidth - 20,
    h = window.innerHeight,
    middle = w / 2;
  var linkDistance = 300;

  var colors = d3.scale.category20();

  var svg = d3.select("body")
    .append("svg:svg")
    .attr("width", w)
    .attr("height", h)
    .style("z-index", -10)
    .attr("id", "svg");

  svg.append('svg:defs').selectAll('marker')
   .data(['end'])
  .enter()
  .append('svg:marker')
   .attr({
    'id': "arrowhead",
    'viewBox': '0 -5 10 10',
     'refX': 22,
     'refY': 0,
     'orient': 'auto',
     'markerWidth': 20,
     'markerHeight': 20,
     'markerUnits': "strokeWidth",
     'xoverflow': 'visible'
   })
  .append('svg:path')
  .attr('d', 'M0,-5L10,0L0,5')
  .attr('fill', '#ccc');








  var force = d3.layout.force();

  var nodes = force.nodes(),
    links = force.links();

  var update = function() {

    var path = svg.selectAll("path.link")
      .data(force.links());

    path.enter().append("svg:path")
      .attr("id", function(d) {
        return d.source.id + "-" + d.value + "-" + d.target.id;
      })
      .attr("class", "link")
      .attr('marker-end', 'url(#arrowhead)');

    path.exit().remove();

    var pathInvis = svg.selectAll("path.invis")
      .data(force.links());

    pathInvis.enter().append("svg:path")
      .attr("id", function(d) {
        return "invis_" + d.source.id + "-" + d.value + "-" + d.target.id;
      })
      .attr("class", "invis");

    pathInvis.exit().remove();

    var pathLabel = svg.selectAll(".pathLabel")
      .data(force.links());

    pathLabel.enter().append("g").append("svg:text")
      .attr("class", "pathLabel")
      .append("svg:textPath")
      .attr("startOffset", "50%")
      .attr("text-anchor", "middle")
      .attr("xlink:href", function(d) {
        return "#invis_" + d.source.id + "-" + d.value + "-" + d.target.id;
      })
      .style("fill", "#cccccc")
      .style("font-size", 10)
      .text(function(d) {
        return d.value;
      });

    var node = svg.selectAll("g.node")
      .data(force.nodes());

    var nodeEnter = node.enter().append("g")
      .attr("class", "node")
      .call(force.drag);

    nodeEnter.append("svg:circle")
      .attr("r", 10)
      .attr("id", function(d) {
        return "Node;" + d.id;
      })
      .attr("class", "nodeStrokeClass")
      .attr("fill", "#0db7ed")

    nodeEnter.append("svg:text")
      .attr("class", "textClass")
      .attr("x", 20)
      .attr("y", ".31em")
      .text(function(d) {
        return d.label;
      });

    node.exit().remove();

    function arcPath(leftHand, d) {
      var x1 = leftHand ? d.source.x : d.target.x,
        y1 = leftHand ? d.source.y : d.target.y,
        x2 = leftHand ? d.target.x : d.source.x,
        y2 = leftHand ? d.target.y : d.source.y,
        dx = x2 - x1,
        dy = y2 - y1,
        dr = Math.sqrt(dx * dx + dy * dy),
        drx = dr,
        dry = dr,
        sweep = leftHand ? 0 : 1;
      siblingCount = countSiblingLinks(d.source, d.target)
      xRotation = 0,
        largeArc = 0;

      if (siblingCount > 1) {
        var siblings = getSiblingLinks(d.source, d.target);
        console.log(siblings);
        var arcScale = d3.scale.ordinal()
          .domain(siblings)
          .rangePoints([1, siblingCount]);
        drx = drx / (1 + (1 / siblingCount) * (arcScale(d.value) - 1));
        dry = dry / (1 + (1 / siblingCount) * (arcScale(d.value) - 1));
      }

      return "M" + x1 + "," + y1 + "A" + drx + ", " + dry + " " + xRotation + ", " + largeArc + ", " + sweep + " " + x2 + "," + y2;
    }

    force.on("tick", function(e) {
      var q = d3.geom.quadtree(nodes),
        i = 0,
        n = nodes.length,
        k = .1 * e.alpha;

      while (++i < n) q.visit(collide(nodes[i]));

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

      path.attr("d", function(d) {
        return arcPath(true, d);
      });

      pathInvis.attr("d", function(d) {
        return arcPath(d.source.x < d.target.x, d);
      });
    });

    force
      .charge(-10000)
      .friction(0.5)
      .linkDistance(linkDistance)
      .size([w, h])
      .start();
    keepNodesOnTop();

  }

  update();

  function collide(node) {
    var r = node.radius + 16,
      nx1 = node.x - r,
      nx2 = node.x + r,
      ny1 = node.y - r,
      ny2 = node.y + r;
    return function(quad, x1, y1, x2, y2) {
      if (quad.point && (quad.point !== node)) {
        var x = node.x - quad.point.x,
          y = node.y - quad.point.y,
          l = Math.sqrt(x * x + y * y),
          r = node.radius + quad.point.radius;
        if (l < r) {
          l = (l - r) / l * .5;
          node.x -= x *= l;
          node.y -= y *= l;
          quad.point.x += x;
          quad.point.y += y;
        }
      }
      return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
    };
  }
}

function drawGraph() {
  graph = new myGraph();
  graph.initialize();
}

drawGraph();

function keepNodesOnTop() {
  $(".nodeStrokeClass").each(function(index) {
    var gNode = this.parentNode;
    gNode.parentNode.appendChild(gNode);
  });






  function fade(opacity) {
    return function(d) {
      node.style("stroke-opacity", function(o) {
        thisOpacity = isConnected(d,o) ? 1 :opacity;
        this.setAttribute('fill-opacity',thisOpacity);
        return thisOpacity;
      });

  }


}; //end of function











}

0 个答案:

没有答案