EzDev.org

d3

A JavaScript visualization library for HTML and SVG. D3.js - Data-Driven Documents


A good book for learning D3.js [closed]

I saw d3js via this Skinny!

I was interested and bought this book!, I may be wrong, however found it un-fulfilling.

does anyone have prime material for mastering d3js for data visualisation?

I can see alot of potential for d3js and am very keen and interested.

thanks in advance!

update: I just completed reading Interactive Data Visualization for the Web by Scott Murray, great book! try it, its free.


Source: (StackOverflow)

D3 javascript Difference between foreach and each

What is the difference between forEach and each in D3js?


Source: (StackOverflow)

d3 js - loading json without a http get

I am learning d3. There are certain ways of loading the data in d3 js. But all of them seem to make a HTTP GET. In my scenario, I already have the json data in a string. How can I use this string instead of making another http request? I tried to look for documentation for this but found none.

This works:

d3.json("/path/flare.json", function(json) {
    //rendering logic here
}

Now, if I have:

//assume this json comes from a server (on SAME DOMAIN)
var myjson = '{"name": "flare","children": [{"name": "analytics","children": [{"name": "cluster","children": [{"name": "MergeEdge", "size": 10 }]}]}]}'; 

How do I use already computed 'myjson' in d3 & avoid a async call to server? Thanks.


Source: (StackOverflow)

D3.js force directed graph, reduce edge crossings by making edges repel each other

So i have a page already which draws a force directed graph, like the one shown here.

And that works fine. I'm using the JS from here, with a few tweaks to spread out the nodes slightly nicer.

These are more or less the only differences:

d3.json("force.json", function(json) {
  var force = d3.layout.force()
      .gravity(0.1)
      .charge(-2000)
      .linkDistance(1)
      .linkStrength(0.1)
      .nodes(json.nodes)
      .links(json.links)
      .size([w, h])
      .start();

Where reducing the link strength seems to make the links more like springs, so it becomes similar to the Fruchterman & Reingold technique often used. This works reasonably well, but only for fairly small graphs. With larger graphs the number of crossings just goes up - as one would expect, but the solution it lands on is normally far from optimal. I'm not looking for a method to get the optimal solution, I know that's very difficult. I would just like it to have some crude addition that tries to force the lines apart as well as the nodes.

Is there a way to add a repulsion between in links, as well as between the nodes? I'm not familiar with the way D3 force works, and i can't seem to find anything that says this is possible...


Source: (StackOverflow)

Updating SVG Element Z-Index With D3

What is an effective way to bring an SVG element to the top of the z-order, using the D3 library?

My specific scenario is a pie chart which highlights (by adding a stroke to the path) when the mouse is over a given piece. The code block for generating my chart is below:

svg.selectAll("path")
    .data(d)
  .enter().append("path")
    .attr("d", arc)
    .attr("class", "arc")
    .attr("fill", function(d) { return color(d.name); })
    .attr("stroke", "#fff")
    .attr("stroke-width", 0)
    .on("mouseover", function(d) {
        d3.select(this)
            .attr("stroke-width", 2)
            .classed("top", true);
            //.style("z-index", 1);
    })
    .on("mouseout", function(d) {
        d3.select(this)
            .attr("stroke-width", 0)
            .classed("top", false);
            //.style("z-index", -1);
    });

I've tried a few options, but no luck so far. Using style("z-index") and calling classed both did not work.

The "top" class is defined as follows in my CSS:

.top {
    fill: red;
    z-index: 100;
}

The fill statement is there to make sure I knew it was turning on/off correctly. It is.

I've heard using sort is an option, but I'm unclear on how it would be implemented for bringing the "selected" element to the top.

UPDATE:

I fixed my particular situation with the following code, which adds a new arc to the SVG on the mouseover event to show a highlight.

svg.selectAll("path")
    .data(d)
  .enter().append("path")
    .attr("d", arc)
    .attr("class", "arc")
    .style("fill", function(d) { return color(d.name); })
    .style("stroke", "#fff")
    .style("stroke-width", 0)
    .on("mouseover", function(d) {
        svg.append("path")
          .attr("d", d3.select(this).attr("d"))
          .attr("id", "arcSelection")
          .style("fill", "none")
          .style("stroke", "#fff")
          .style("stroke-width", 2);
    })
    .on("mouseout", function(d) {
        d3.select("#arcSelection").remove();
    });

Source: (StackOverflow)

rotate x axis text in d3

I am new to d3 and svg coding and am looking for a way to rotate text on the xAxis of a chart. My problem is that typically the xAxis titles are longer than the bars in the bar chart are wide. So I'm looking to rotate the text to run vertically (rather than horizontally) beneath the xAxis.

I've tried adding the transform attribute: .attr("transform", "rotate(180)")

But when I do that, the text disappears altogether. I've tried increasing the height of the svg canvas, but still was unable to view the text.

Any thoughts on what I'm doing wrong would be great. Do I need to also adjust the x and y positions? And, if so, by how much (hard to troubleshoot when I can see it in Firebug).


Source: (StackOverflow)

Learning d3.js for data visualisation [closed]

I want to start learning to make data visualisations (as side project in my PhD) preferably with the D3.js package. I do not have java-experience but i do have a background in OOP as i mostly work in python. As such, I was wondering what's the best way to learn working with d3 and which environment one could recommend me.


Source: (StackOverflow)

Fix Node Position in D3 Force-Directed Layout

I want some of the nodes in my force-directed layout to ignore the force and stay in fixed positions based on the attribute of the node, while still being able to be dragged and exert repulsion on other nodes and maintain their link lines. I thought it would be as simple as this:

    force.on("tick", function() {
        vis.selectAll("g.node")
            .attr("transform", function(d) {
                return (d.someAttribute == true) ?
                    "translate(" + d.xcoordFromAttribute + "," + d.ycoordFromAttribute +")" :
                    "translate(" + d.x + "," + d.y + ")"
            });
     });

I have also tried to manually set the node's x and y attributes on-tick, but then the links continue to float out to where the node would be if it was affected by the force.

Obviously I have a basic misunderstanding of how this is supposed to work, so could somebody point me to an example where some nodes are fixed in their position (but still draggable) and the rest of the nodes are floating around force-directed-like, and all the links are still working?


Source: (StackOverflow)

Invoke a callback at the end of a transition

I need to make a FadeOut method (similar to jQuery) using D3.js. What I need to do is to set the opacity to 0 using transition().

d3.select("#myid").transition().style("opacity", "0");

The problem is that I need a callback to realize when the transition has finished. How can I implement a callback?


Source: (StackOverflow)

Is there a way to zoom into a D3 force layout graph?

D3 has a force directed layout here. Is there a way to add zooming to this graph? Currently, I was able to capture the mouse wheel event but am not really sure how to write the redraw function itself. Any suggestions?

    var vis = d3.select("#graph")
        .append("svg:svg")
        .call(d3.behavior.zoom().on("zoom", redraw)) // <-- redraw function
        .attr("width", w)
        .attr("height", h);

Source: (StackOverflow)

Adding new nodes to Force-directed layout

First question on Stack Overflow, so bear with me! I am new to d3.js, but have been consistently amazed by what others are able to accomplish with it... and almost as amazed by how little headway I've been able to make with it myself! Clearly I'm not grokking something, so I hope that the kind souls here can show me the light.

My intention is to make a reusable javascript function which simply does the following:

  • Creates a blank force-directed graph in a specified DOM element
  • Allows you to add and delete labeled, image-bearing nodes to that graph, specifying connections between them

I've taken http://bl.ocks.org/950642 as a starting point, since that's essentially the kind of layout I want to be able to create:

enter image description here

Here's what my code looks like:

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript" src="jquery.min.js"></script>
    <script type="text/javascript" src="underscore-min.js"></script>
    <script type="text/javascript" src="d3.v2.min.js"></script>
    <style type="text/css">
        .link { stroke: #ccc; }
        .nodetext { pointer-events: none; font: 10px sans-serif; }
        body { width:100%; height:100%; margin:none; padding:none; }
        #graph { width:500px;height:500px; border:3px solid black;border-radius:12px; margin:auto; }
    </style>
</head>
<body>
<div id="graph"></div>
</body>
<script type="text/javascript">

function myGraph(el) {

    // Initialise the graph object
    var graph = this.graph = {
        "nodes":[{"name":"Cause"},{"name":"Effect"}],
        "links":[{"source":0,"target":1}]
    };

    // Add and remove elements on the graph object
    this.addNode = function (name) {
        graph["nodes"].push({"name":name});
        update();
    }

    this.removeNode = function (name) {
        graph["nodes"] = _.filter(graph["nodes"], function(node) {return (node["name"] != name)});
        graph["links"] = _.filter(graph["links"], function(link) {return ((link["source"]["name"] != name)&&(link["target"]["name"] != name))});
        update();
    }

    var findNode = function (name) {
        for (var i in graph["nodes"]) if (graph["nodes"][i]["name"] === name) return graph["nodes"][i];
    }

    this.addLink = function (source, target) {
        graph["links"].push({"source":findNode(source),"target":findNode(target)});
        update();
    }

    // set up the D3 visualisation in the specified element
    var w = $(el).innerWidth(),
        h = $(el).innerHeight();

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

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

    var update = function () {

        var link = vis.selectAll("line.link")
            .data(graph.links);

        link.enter().insert("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(graph.nodes);

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

        node.append("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");

        node.append("text")
            .attr("class", "nodetext")
            .attr("dx", 12)
            .attr("dy", ".35em")
            .text(function(d) { return d.name });

        node.exit().remove();

        force.on("tick", function() {
          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 + ")"; });
        });

        // Restart the force layout.
        force
          .nodes(graph.nodes)
          .links(graph.links)
          .start();
    }

    // Make it all go
    update();
}

graph = new myGraph("#graph");

// These are the sort of commands I want to be able to give the object.
graph.addNode("A");
graph.addNode("B");
graph.addLink("A", "B");

</script>
</html>

Every time I add a new node, it re-labels all of the existing nodes; these pile on top of each other and things start to get ugly. I understand why this is: because when I call the update() function function upon adding a new node, it does a node.append(...) to the entire data set. I can't figure out how to do this for only the node I'm adding... and I can only apparently use node.enter() to create a single new element, so that doesn't work for the additional elements I need bound to the node. How can I fix this?

Thank you for any guidance that you're able to give on any of this issue!

Edited because I quickly fixed a source of several other bugs that were previously mentioned


Source: (StackOverflow)

D3.js: what is 'g' in .append("g") D3.js code?

I am new to D3.js, started learning today only

I looked the the donut example and found this code

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
  .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

I searched for documentation, but did not understood what .append("g") is appending

Is it even D3 specific?

Looking for guidance here


Source: (StackOverflow)

Creating a table linked to a csv file

I am trying to create a table linked to a *.csv file using d3, but all I get is a blank webpage. Even with the example Crimea I get a blank page.
I would be grateful to be directed or shown a working example or a suggestion of what I am doing wrong.


Source: (StackOverflow)

D3 within an AngularJS app

I'm trying to create my first app with AngularJS. It looks neat, but there's a lot of abstraction, and I'm just curious if anyone has advice on the most idiomatic way to use the angular methodology to update visuals created with d3js.

Thanks, bp


Source: (StackOverflow)

Understanding how D3.js binds data to nodes

I'm reading through the D3.js documentation, and am finding it hard to understand the selection.data method from the documentation.

This is the example code given in the documentation:

var matrix = [
  [11975,  5871, 8916, 2868],
  [ 1951, 10048, 2060, 6171],
  [ 8010, 16145, 8090, 8045],
  [ 1013,   990,  940, 6907]
];

var tr = d3.select("body").append("table").selectAll("tr")
    .data(matrix)
  .enter().append("tr");

var td = tr.selectAll("td")
    .data(function(d) { return d; })
  .enter().append("td")
    .text(function(d) { return d; });

I understand most of this, but what is going on with the .data(function(d) { return d; }) section of the var td statement?

My best guess is as follows:

  • The var tr statement has bound a four-element array to each tr node
  • The var td statement then uses that four-element array as its data, somehow

But how does .data(function(d) { return d; }) actually get that data, and what does it return?


Source: (StackOverflow)