javascript - Controlling bar position with tickValues in d3.js -
i'm trying build multi series bar chart using d3 running problems due sparse nature of dataset.
i want force x-axis have tick every day, if there no data. test data have can have data points weeks apart i'm expecting wide areas no bars - fine.
i thought force xaxis use set of predefined ticks using tickvalues array, these leads strange display of overlaying text each day on top of days have data.
i've included screenshot of mean.
i feeling i'm supposed when calculating width of bars can't figure out might be.
code:
var data = []; var tickvalues = []; var max = _.max(chartdata.tabular, function(assessment) { return assessment.dateutc; }); var min = _.min(chartdata.tabular, function(assessment) { return assessment.dateutc; }); var iter = moment.twix(min.dateutc, max.dateutc).iterate("days"); while(iter.hasnext()){ var momentobj = iter.next(); var assessment = _.find(chartdata.tabular, {'date': momentobj.format('dd/mm/yyyy')}); tickvalues.push(momentobj.valueof()); if(assessment != null){ if(assessment.type == 'calculated'){ data.push({date: momentobj.valueof(), calculated: assessment.score, manual: null}); } if(assessment.type == 'manual'){ data.push({date: momentobj.valueof(), calculated: null, manual: assessment.score}); } } } log(data); var margin = {top: 20, right: 55, bottom: 30, left: 40}, width = $('#cahai-chart').width() - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var x = d3.scale.ordinal() .rangeroundbands([0, width], .1); var y = d3.scale.linear() .rangeround([height, 0]); var xaxis = d3.svg.axis() .scale(x) .orient("bottom") .tickvalues(tickvalues) .tickformat(function(d){return d3.time.format('%d/%m/%y')(new date(d))}); var yaxis = d3.svg.axis() .scale(y) .orient("left"); var color = d3.scale.ordinal() .range(["#001c9c","#101b4d","#475003","#9c8305","#d3c47c"]); var svg = d3.select("#cahai-chart svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var labelvar = 'date'; var varnames = d3.keys(data[0]).filter(function (key) { return key !== labelvar;}); color.domain(varnames); data.foreach(function (d) { var y0 = 0; d.mapping = varnames.map(function (name) { return { name: name, label: d[labelvar], y0: y0, y1: y0 += +d[name] }; }); d.total = d.mapping[d.mapping.length - 1].y1; }); x.domain(data.map(function (d) { return d.date; })); y.domain([0, d3.max(data, function (d) { return d.total; })]); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xaxis); svg.append("g") .attr("class", "y axis") .call(yaxis) .append("text") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", ".71em") .style("text-anchor", "end") .text("score"); var selection = svg.selectall(".series") .data(data) .enter().append("g") .attr("class", "series") .attr("transform", function (d) { return "translate(" + x(d.date) + ",0)"; }); selection.selectall("rect") .data(function (d) { return d.mapping; }) .enter().append("rect") .attr("width", x.rangeband()) .attr("y", function (d) { return y(d.y1); }) .attr("height", function (d) { return y(d.y0) - y(d.y1); }) .style("fill", function (d) { return color(d.name); }) .style("stroke", "grey") .on("mouseover", function (d) { showpopover.call(this, d); }) .on("mouseout", function (d) { removepopovers(); }) var legend = svg.selectall(".legend") .data(varnames.slice().reverse()) .enter().append("g") .attr("class", "legend") .attr("transform", function (d, i) { return "translate(55," + * 20 + ")"; }); legend.append("rect") .attr("x", width - 10) .attr("width", 10) .attr("height", 10) .style("fill", color) .style("stroke", "grey"); legend.append("text") .attr("x", width - 12) .attr("y", 6) .attr("dy", ".35em") .style("text-anchor", "end") .text(function (d) { return d; }); function removepopovers () { $('.popover').each(function() { $(this).remove(); }); } function showpopover (d) { $(this).popover({ title: d.name, placement: 'auto top', container: 'body', trigger: 'manual', html : true, content: function() { return "date: " + d3.time.format('%d/%m/%y')(new date(d.label)) + "<br/>score: " + d3.format(",")(d.value ? d.value: d.y1 - d.y0); } }); $(this).popover('show') }
an ordinal scale show many ticks there values in domain. need pass full array of dates domain.
replace line
x.domain(data.map(function (d) { return d.date; }));
with this
x.domain(tickvalues);
it looks have else set correctly, space bars out along axis , make them slimmer.
Comments
Post a Comment