2

I'm playing with the following Javascript + SVG + D3 code.
http://bl.ocks.org/1095795

The code is here:
https://gist.github.com/1095727

In short, I need unique images for each node (instead of the duplicated smiley face image as it's pulling now), but I'm not savvy enough to make it happen. Any help would be appreciated.

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js"></script>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.layout.js"></script>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.geom.js"></script>
<style type="text/css">
.link { stroke: #ccc; }
.nodetext { pointer-events: none; font: 10px sans-serif; }
</style>
</head>
<body>
<script type="text/javascript">

var w = 960,
    h = 500

var nodes = [],
    links = [];

var vis = d3.select("body").append("svg:svg")
    .attr("width", w)
    .attr("height", h);

var force = self.force = d3.layout.force()
    .nodes(nodes)
    .links(links)
    .gravity(.05)
    .distance(100)
    .charge(-100)
    .size([w, h]);

force.on("tick", function() {
    var node = vis.selectAll("g.node")
        .data(nodes, function(d) { return d.id;} )
    var link = vis.selectAll("line.link")
        .data(links, function(d) { return d.source.id + ',' + d.target.id})
  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 + ")"; });
});

function recalc() {
    var link = vis.selectAll("line.link")
                  .data(links, function(l) { return l.source.id + '-' + l.target.id; });

    link.enter().append("svg:line")
                .attr("class", "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; });

    link.exit().remove();

    var node = vis.selectAll("g.node")
              .data(nodes, function(d) { return d.dpid;}).call(force.drag);

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

    nodeEnter.append("svg:image")
        .attr("class", "circle")
        .attr("xlink:href", "https://d3nwyuy0nl342s.cloudfront.net/images/icons/public.png")
        .attr("x", "-8px")
        .attr("y", "-8px")
        .attr("width", "16px")
        .attr("height", "16px");

    nodeEnter.append("svg:text")
        .attr("class", "nodetext")
        .attr("dx", 12)
        .attr("dy", ".35em")
        .text(function(d) { return d.id });

    node.exit().remove();

    force.start();

}


/* Scenario */

/* step 1: add three nodes and three links */
function step1() {
    var nA = {id: 'aaa'};
    var nB = {id: 'bbb'};
    var nC = {id: 'ccc'};
    nodes.push(nA);
    nodes.push(nB);
    nodes.push(nC);

    var lAB = {source: nA, target: nB};
    var lAC = {source: nA, target: nC};
    var lBC = {source: nB, target: nC};
    links.push(lAB );
    links.push(lAC);
    links.push(lBC);

    recalc();
}

/* step 2: node B disappears with links */
function step2() {
    nodes = nodes.filter(function(n) { return n.id !== 'bbb'; });
    links = links.filter(function(l) { return (l.source.id !== 'bbb' && l.target.id !== 'bbb'); });

    recalc();
}

/* step 3: node B reappears with links */
function step3() {
    var nB = {id: 'bbb'};

    nodes.push(nB);

    /* find exiting nodes for links */
    var nA = nodes.filter(function(n) { return n.id === 'aaa'; })[0];
    var nC = nodes.filter(function(n) { return n.id === 'ccc'; })[0];

    var lAB = {source: nA, target: nB};
    var lBC = {source: nB, target: nC};
    links.push(lAB);
    links.push(lBC);

    recalc();
}

window.setTimeout(step1, 2000);
window.setTimeout(step2, 4000);
window.setTimeout(step3, 6000);

force.start();
recalc();

</script>
</body>
</html>
VividD
  • 10,456
  • 6
  • 64
  • 111
  • 1) Please cut down the code to the part you're actually concerned about. 2) When you say "unique" images, do you mean that they should be keyed off some element of the data? or randomly chosen from a set of unique images? or? – nrabinowitz Oct 11 '12 at 23:46
  • Right now, 1 image (public.png) is added to each node at build time by this code: ----- `code nodeEnter.append("svg:image") blahblahblah "d3nwyuy0nl342s.cloudfront.net/images/icons/public.png";) ` ----- I'd like to add a different/specific image for each built node. In my case, it doesn't need to be dynamic...I'll have a set number of nodes, etc. In short, I don't know how to access a node after it's been dynamically built nor do I know how to change/append an svg image to said nodes – Eric Stralow Oct 12 '12 at 14:06

1 Answers1

2

It looks like you're trying to add a different image for each node, instead of the one image added here:

nodeEnter.append("svg:image")
    .attr("class", "circle")
    .attr("xlink:href", "https://d3nwyuy0nl342s.cloudfront.net/images/icons/public.png")

This adds the image at node creation time, which sounds like it would be sufficient for your purposes. All you need to do is supply a function instead of a string for the relevant .attr() call. If you had an array of image URLs to use, you could get them in sequence like this:

nodeEnter.append("svg:image")
    .attr("class", "circle")
    .attr("xlink:href", function(d, i) {
        // d is the node data, i is the index of the node
        return myImages[i];
    })

or, if you had image URLs in the node data itself:

nodeEnter.append("svg:image")
    .attr("class", "circle")
    .attr("xlink:href", function(d, i) {
        // d is the node data, i is the index of the node
        return d.nodeImageUrl;
    })
nrabinowitz
  • 55,314
  • 10
  • 149
  • 165