javascript - Overlay line graph on stacked bar in d3.js when x-axis is strings -
i'm having issue adding line graph in svg, partially think because x-axis using months strings. wondering if there way incorporate line when don't have standard date.
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 } //assets , debts var data = [[{y:3000},{y:2000},{y:2500},{y:1000},{y:3000},{y:5000}], [{y:-700},{y:-300},{y:-1000},{y:-500},{y:-1100},{y:-2000}]] //debt assets var ratio = [] (var = 0; i<data[0].length; i++){ ratio.push(data[1][i]/data[0][i]*-1); } date.prototype.monthnames = [ "january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"]; date.prototype.getmonthname = function() { return this.monthnames[this.getmonth()]; }; // creates array of previous 6 months var d = new date(); var n = d.getmonth(); var last_6_months = []; for(var i=data[0].length; i>0; i--){ temp_month = d; temp_month.setmonth(n - i); last_6_months.push(temp_month.getmonthname()); } //combine ratio , dates use in svg line var data1 = [] for(var i=0; i<data[0].length; i++){ var object = {} object.month = last_6_months[i] object.ratio = ratio[i] data1.push(object) } var h=500 ,w=500 ,margin=40 ,color = d3.scale.category10() ,x = d3.scale.ordinal() .domain(last_6_months) .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") //variables used in line graph ,y1 = d3.scale.linear() .range([h-margin,0+margin]) ,yaxisright = d3.svg.axis().scale(y1).orient("right"); ,valueline = d3.svg.line() .x(function(d) { return x(d.month); }) .y(function(d) { return y1(d.ratio); }) .interpolate("linear"); y1.domain(ratio.extent) 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()) //line ratio svg.data(data1).enter().append("path") .attr("class", "line") .attr("d", valueline(data1)); 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) //axis ratio svg.append("g").attr("class", "axis y").attr("transform", "translate(" + x(margin) + " 0)").style("fill", "red").call(yaxisright);
the d3.svg.line
functions have no problem dealing ordinal scale. however, use ordinal.rangepoints()
method when want points line. way, point on line match point on axis.
since you're using ordinal.rangebands()
in order position bar chart, need specify want point line in middle of bar. can in x-accessor function of d3.svg.line
object:
valueline = d3.svg.line() .x(function(d) { return x(d.month) + x.rangeband()/2; }) .y(function(d) { return y1(d.ratio); }) .interpolate("linear");
if you're still having problems, try put simplified working example, or @ least post more specific details of problem.
Comments
Post a Comment