I think this should be fairly simple, but I'm new to D3 and don't know where to start. I'd like to set a minumum height to the bars in my bargraph so that even bars with a value of 0 are still visible.
I'd also like this to be accurately represented by the Y axis (ideally by adding a buffer between the X axis and the start of 0 on the Y axis).
Is there a simple way to do this with a dynamic bar graph? The range on the Y axis could range from having a max of 2 to a max of 50,000, but I still want every bar to have height of some sort.
I apologize for the length of this:
link: function(scope, iElement, iAttrs) {
var scope = scope;
var chart = '';
var margin = {top: 20, right: 100, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
scope.postdetails = false;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.range([height, 0]);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5, "");
var abbrevNum = function (d) {
var prefix = d3.formatPrefix(d);
return d3.round(prefix.scale(d),1) + prefix.symbol;
};
var initChart = function(){
$('.main-report-chart').remove();
x = null;
y = null;
x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
y = d3.scale.linear()
.range([height, 0]);
yAxis = d3.svg.axis()
.tickFormat(function(d) { return abbrevNum(d); })
.scale(y)
.orient("left")
.ticks(5, "");
chart = d3.select(iElement[0]).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr('class','main-report-chart')
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
};
var getMean = function(data){
var meanData = d3.mean(data,function(d){return eval('d.'+scope.metric)});
var meanArray = [];
meanArray.push(meanData);
return meanArray;
};
var watchCount = 0;
var svg='';
var newData = {}
scope.$watch('reportData', function(newVals, oldVals) {
if(newVals === oldVals && newVals !== undefined){
watchCount++;
initChart();
newData = newVals;
return scope.render(newVals);
}
if(watchCount==2){
if(newVals){
initChart();
newData = newVals;
return scope.render(newVals);
}
} else{
if(newVals){
initChart();
newData = newVals;
return scope.render(newVals);
}
}
}, true);
var tempValues = {};
scope.$watch('metric', function(newVals, oldVals) {
if(newVals){
if(scope.reportData){
// where redraw happens:
return scope.render(newData);
}
}
}, false);
scope.render = function(data){
if (scope.metric !== "") {
x.domain(data.map(function(d) { return d.id; }));
y.domain([0, d3.max(data, function(d) { return eval('d.' + scope.metric); })]);
chart.select(".x.axis").remove();
chart
.append("g")
.append("line")
.attr('x1',0)
.attr('x2',width)
.attr('y1',height )
.attr('y2',height)
.attr('stroke-width','2')
.attr("class", "domain");
chart.select(".y.axis").remove();
chart.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", -40)
.attr('class','label')
.attr("x", -height)
.attr("dy", ".71em")
.style("text-anchor", "begin")
.text(scope.label);
var bar = chart.selectAll(".bar")
.data(data, function(d) { return d.id; });
// new data:
bar.enter()
.append("g")
.attr("class", "bar-container")
.append("rect")
.attr("class", "bar")
.attr('fill','#4EC7BD')
.attr("x", function(d) { return x(d.id); })
.attr("y", function(d) { return y(eval('d.'+scope.metric)); })
.attr("height", function(d) { return height - y(eval('d.'+scope.metric)); })
.attr("width", x.rangeBand())
.on('click', function(d){
scope.showDetails(d, eval('d.'+scope.metric))
});
bar.exit().remove();
bar
.transition()
.duration(750)
.attr("y", function(d) { return y(eval('d.'+scope.metric)); })
.attr("height", function(d) { return height - y(eval('d.'+scope.metric)); });
var labeltip = chart.selectAll('.tip')
.data(data, function(d) { return d.id; });
var meanData = getMean(data);
var average = chart.selectAll(".average")
.data(meanData);
average.enter()
.append("line")
.attr("class", "average")
.attr('stroke-width','2')
.attr('stroke','#3D3F49')
.attr('x1',0)
.attr('x2',width)
.attr('y1',y(meanData))
.attr('y2',y(meanData));
average.exit().remove();
average.transition()
.duration(750)
.attr('y1',y(meanData))
.attr('y2',y(meanData));
var avgbox = chart.selectAll(".avg-box")
.data(meanData);
avgbox.enter().append("rect")
.attr('class','avg-box')
.attr('width',75)
.attr('height',20)
.attr('fill','#3D3F49')
.attr('x',width )
.attr('rx',5)
.attr('y',y(meanData)-10);
var avgtext = chart.selectAll(".avg-text")
.data(meanData);
avgtext.enter().append('text')
.text('AVG '+ abbrevNum(Math.round(meanData)))
.attr('x',width +8)
.attr('class','avg-text')
.attr('y',y(meanData+15))
.attr('fill','white');
avgbox.exit().remove();
avgbox.transition()
.duration(750)
.attr('y',y(meanData)-10);
avgtext.exit().remove();
avgtext.transition()
.duration(750)
.text('AVG '+ abbrevNum(Math.round(meanData)))
.attr('y',y(meanData)+4);
}
};
}
I think this should be fairly simple, but I'm new to D3 and don't know where to start. I'd like to set a minumum height to the bars in my bargraph so that even bars with a value of 0 are still visible.
I'd also like this to be accurately represented by the Y axis (ideally by adding a buffer between the X axis and the start of 0 on the Y axis).
Is there a simple way to do this with a dynamic bar graph? The range on the Y axis could range from having a max of 2 to a max of 50,000, but I still want every bar to have height of some sort.
I apologize for the length of this:
link: function(scope, iElement, iAttrs) {
var scope = scope;
var chart = '';
var margin = {top: 20, right: 100, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
scope.postdetails = false;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.range([height, 0]);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5, "");
var abbrevNum = function (d) {
var prefix = d3.formatPrefix(d);
return d3.round(prefix.scale(d),1) + prefix.symbol;
};
var initChart = function(){
$('.main-report-chart').remove();
x = null;
y = null;
x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
y = d3.scale.linear()
.range([height, 0]);
yAxis = d3.svg.axis()
.tickFormat(function(d) { return abbrevNum(d); })
.scale(y)
.orient("left")
.ticks(5, "");
chart = d3.select(iElement[0]).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr('class','main-report-chart')
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
};
var getMean = function(data){
var meanData = d3.mean(data,function(d){return eval('d.'+scope.metric)});
var meanArray = [];
meanArray.push(meanData);
return meanArray;
};
var watchCount = 0;
var svg='';
var newData = {}
scope.$watch('reportData', function(newVals, oldVals) {
if(newVals === oldVals && newVals !== undefined){
watchCount++;
initChart();
newData = newVals;
return scope.render(newVals);
}
if(watchCount==2){
if(newVals){
initChart();
newData = newVals;
return scope.render(newVals);
}
} else{
if(newVals){
initChart();
newData = newVals;
return scope.render(newVals);
}
}
}, true);
var tempValues = {};
scope.$watch('metric', function(newVals, oldVals) {
if(newVals){
if(scope.reportData){
// where redraw happens:
return scope.render(newData);
}
}
}, false);
scope.render = function(data){
if (scope.metric !== "") {
x.domain(data.map(function(d) { return d.id; }));
y.domain([0, d3.max(data, function(d) { return eval('d.' + scope.metric); })]);
chart.select(".x.axis").remove();
chart
.append("g")
.append("line")
.attr('x1',0)
.attr('x2',width)
.attr('y1',height )
.attr('y2',height)
.attr('stroke-width','2')
.attr("class", "domain");
chart.select(".y.axis").remove();
chart.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", -40)
.attr('class','label')
.attr("x", -height)
.attr("dy", ".71em")
.style("text-anchor", "begin")
.text(scope.label);
var bar = chart.selectAll(".bar")
.data(data, function(d) { return d.id; });
// new data:
bar.enter()
.append("g")
.attr("class", "bar-container")
.append("rect")
.attr("class", "bar")
.attr('fill','#4EC7BD')
.attr("x", function(d) { return x(d.id); })
.attr("y", function(d) { return y(eval('d.'+scope.metric)); })
.attr("height", function(d) { return height - y(eval('d.'+scope.metric)); })
.attr("width", x.rangeBand())
.on('click', function(d){
scope.showDetails(d, eval('d.'+scope.metric))
});
bar.exit().remove();
bar
.transition()
.duration(750)
.attr("y", function(d) { return y(eval('d.'+scope.metric)); })
.attr("height", function(d) { return height - y(eval('d.'+scope.metric)); });
var labeltip = chart.selectAll('.tip')
.data(data, function(d) { return d.id; });
var meanData = getMean(data);
var average = chart.selectAll(".average")
.data(meanData);
average.enter()
.append("line")
.attr("class", "average")
.attr('stroke-width','2')
.attr('stroke','#3D3F49')
.attr('x1',0)
.attr('x2',width)
.attr('y1',y(meanData))
.attr('y2',y(meanData));
average.exit().remove();
average.transition()
.duration(750)
.attr('y1',y(meanData))
.attr('y2',y(meanData));
var avgbox = chart.selectAll(".avg-box")
.data(meanData);
avgbox.enter().append("rect")
.attr('class','avg-box')
.attr('width',75)
.attr('height',20)
.attr('fill','#3D3F49')
.attr('x',width )
.attr('rx',5)
.attr('y',y(meanData)-10);
var avgtext = chart.selectAll(".avg-text")
.data(meanData);
avgtext.enter().append('text')
.text('AVG '+ abbrevNum(Math.round(meanData)))
.attr('x',width +8)
.attr('class','avg-text')
.attr('y',y(meanData+15))
.attr('fill','white');
avgbox.exit().remove();
avgbox.transition()
.duration(750)
.attr('y',y(meanData)-10);
avgtext.exit().remove();
avgtext.transition()
.duration(750)
.text('AVG '+ abbrevNum(Math.round(meanData)))
.attr('y',y(meanData)+4);
}
};
}
Share
Improve this question
edited May 18, 2015 at 20:07
torox
4901 gold badge3 silver badges11 bronze badges
asked May 18, 2015 at 19:20
Lauren FLauren F
1,3224 gold badges18 silver badges31 bronze badges
2
-
accurately represented by the Y axis
, how would you do that? Start the y-axis at a negative number? – Mark Commented May 18, 2015 at 19:25 - Possibly? Or by adding a buffer between the X axis and the start of 0 – Lauren F Commented May 18, 2015 at 19:39
2 Answers
Reset to default 6I'd set the y-axis minimum to a negative number that is 2% of your maximum y value:
var maximumY = d3.max(data, function(d) {
return d.frequency;
});
y.domain([-(maximumY * .02), maximumY]);
Here's a quick example built off the classic d3
bar chart example. I think it produces a nice effect:
Hey at this scenario i have added minimum function to get minimum value represented number as 10% of chart bar.
// you must take the maximum number in you chart to be pared after
var max = d3.max(data, function (d) { return Math.max(d.Open, d.Closed); });
// on d3 where you draw the bar chart use the function
.attr("y", function (d) {
var barY = getMinimumValueChartBar(d.Open, max);
return y(barY);
})
.attr("height", function (d) {
var barY = getMinimumValueChartBar(d.Open, max);
return height - y(barY);
})
// this method pute if the value need to get the minimum value 10% or its zero
function getMinimumValueChartBar(val, max) {
if (val > 0 && max * 0.1 > val) {
val = max * 0.1;
}
return val;
}
Hope it will help anyone..
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744896090a4599704.html
评论列表(0条)