user1477388
user1477388

Reputation: 21430

d3 Bar Chart Add Margins

I would like to make this d3 bar chart (ignore the different colors, that's for grouping which is not what I'm talking about):

enter image description here

Look like this javascript bar chart (specifically, how it has each instance broken up into "links" or "blocks" i.e. there is spacing between each item):

enter image description here

I can do this in javascript fairly easily but I am not sure how to do this in d3.

Can anyone provide any examples of how to break down each item as shown in the graph above?

I have tried this so far:

.append("rect")
    .style("margin", "20")

This is the source for the d3 chart: https://jsfiddle.net/mq2jcfz0/

<!DOCTYPE html>
<html>
<head>
<script src="http://mbostock.github.com/d3/d3.v2.js"></script>
<title>barStack</title>  
<style>
.axis text {
font: 10px sans-serif;
}
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<script type="text/javascript" >
function barStack(d) {
var l = d[0].length
while (l--) {
    var posBase = 0, negBase = 0;
    d.forEach(function(d) {
        d=d[l]
        d.size = Math.abs(d.y)
        if (d.y<0)  {
            d.y0 = negBase
            negBase-=d.size
        } else
        { 
            d.y0 = posBase = posBase + d.size
        } 
    })
}
d.extent= d3.extent(d3.merge(d3.merge(d.map(function(e) { return e.map(function(f) { return [f.y0,f.y0-f.size]})}))))
return d
}

/* Here is an example */

var data = [[{y:3},{y:6},{y:-3}],
        [{y:4},{y:-2},{y:-9}],
        [{y:10},{y:-3},{y:4}]]


var  h=500
,w=500
,margin=10
,color = d3.scale.category10()

,x = d3.scale.ordinal()
    .domain(['abc','abc2','abc3'])
    .rangeRoundBands([margin,w-margin], .1)

,y = d3.scale.linear()
    .range([h-margin,0+margin])

,xAxis = d3.svg.axis().scale(x).orient("bottom").tickSize(6, 0)
,yAxis = d3.svg.axis().scale(y).orient("left")

barStack(data)
y.domain(data.extent)

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

svg.selectAll(".series").data(data)
.enter().append("g").classed("series",true).style("fill", function(d,i) { return color(i)})
    .selectAll("rect").data(Object)
    .enter().append("rect")
        .attr("x",function(d,i) { return x(x.domain()[i])})
        .attr("y",function(d) { return y(d.y0)})
        .attr("height",function(d) { return y(0)-y(d.size)})
        .attr("width",x.rangeBand())

svg.append("g").attr("class","axis x").attr("transform","translate (0 "+y(0)+")").call(xAxis)
svg.append("g").attr("class","axis y").attr("transform","translate ("+x(margin)+" 0)").call(yAxis)

</script>
</body>
</html>

Upvotes: 1

Views: 1635

Answers (1)

cirofdo
cirofdo

Reputation: 1074

You will need to work with the barStack function that deals with arranging the data to stack the bars. You just have to move rects position like this:

var barPad = 0.5;

function barStack(d) {
var l = d[0].length
while (l--) {
    var posBase = 0, negBase = 0;
    d.forEach(function(d) {
        d=d[l]
        d.size = Math.abs(d.y)
        if (d.y<0)  {
            d.y0 = negBase - barPad
            negBase-=d.size + barPad
        } else
        { 
            d.y0 = posBase = posBase + d.size + barPad
        } 
    })
}
d.extent= d3.extent(d3.merge(d3.merge(d.map(function(e) { return e.map(function(f) { return [f.y0,f.y0-f.size]})}))))
return d
}

Upvotes: 1

Related Questions