javascriptd3.jsstream-graph

How to make D3 Streamgraph vertically


I'm new in D3, so my question probably is pretty simple, but for me it's a big problem right now.

Question:

How to make Streamgraph vertically? my JSFiddle

I have this:

enter image description here

I should have this:

enter image description here

Fiddle is here

JS

var dataMetric = [
    {
        "id": 1,
        "title": "Little Inc",
        "metrics": {
            "offers": 665,
            "shares": 20,
            "landings": 1124,
            "leads": 1102,
            "purchases": 88,
            "friends": 74
        }
    },
    {
        "id": 2,
        "title": "Marvin LLC",
        "metrics": {
            "offers": 20,
            "shares": 2,
            "landings": 20,
            "leads": 25,
            "purchases": 28,
            "friends": 18
        }
    },
    {
        "id": 3,
        "title": "Hodkiewicz, Jacobson and O'Conner",
        "metrics": {
            "offers": 834,
            "shares": 8,
            "landings": 759,
            "leads": 683,
            "purchases": 41,
            "friends": 35
        }
    },
    {
        "id": 4,
        "title": "Harber, Fahey and Berge",
        "metrics": {
            "offers": 233,
            "shares": 5,
            "landings": 352,
            "leads": 348,
            "purchases": 31,
            "friends": 25
        }
    }
];

var metrics = ["offers", "shares", "landings", "leads", "purchases", "friends"];
var width = 500,
    height = 200,
    colors = {'0': '#6ff500', '1': '#ffad0a', '2': '#f90035', '3': '#6fD000'},
    stack = d3.layout.stack().offset("expand");
var svg = d3.select("#timeline").append("svg")
    .attr("width", width)
    .attr("height", height);
var y = d3.scale.linear()
    .domain([0, 1])
    .range([height, 0]);
var color = d3.scale.linear()
    .range(["#0D0", "#060"]);


streamed_history(dataMetric)

function streamed_history(data) {
    var m = [];
    data_array = metrics.forEach(function (f, metricIndex) {
        for (var index in data) {
            m[index] = m[index] || [];
            m[index].push({x: metricIndex, y:data[index].metrics[f]});
        }
    })
    layers = stack(m)
    console.log(m)
    layers = dataMetric.map(function (f, i) {
        return {layer: layers[i], companyName: f.title, color: color(i/(dataMetric.length -1))}
    })

    var x = d3.scale.linear()
        .domain([0, metrics.length - 1])
        .range([0, width]);

    var area = d3.svg.area()/*.interpolate("basis")*/
        .x(function(d) { return x(d.x); })
        .y0(function(d) { return y(null); })
        .y1(function(d) { return y(d.y0 + d.y); });

    function fixPath (path) {
        var Lidx = path.indexOf('L');
        var Cidx =  path.slice(Lidx).indexOf('C');
        var PCidx = path.slice(0,Lidx).lastIndexOf('C');
        var lp = path.substr(PCidx, Lidx-PCidx);
        var ss = path.substr(Lidx, Cidx);
        return (path.slice(0,Lidx) + lp + ss + path.slice(Lidx));
    }

    //enter
    svg.selectAll("path")
        .data(layers.reverse())
        .enter().append("path")
        .attr("d", function (d) {
            return fixPath(area(d.layer));
        })
        .style("fill", function(d) { return d.color; });

    //update
    d3.selectAll("path")
        .data(layers)
        .transition()
        .duration(2000)
        .attr("d", function (d) {return fixPath(area(d.layer));});
}

Solution

  • All you need to do is change the x to y and y to x in your area definition:

    var area = d3.svg.area()/*.interpolate("basis")*/
        .y(function(d) { return x(d.x); })
        .x0(function(d) { return y(null); })
        .x1(function(d) { return y(d.y0 + d.y); });
    

    Complete example here.