我很难在d3条形图中管理Y-Scale。 我想根据数据使y尺度动态,但不要超过积分[ticks]多于4个正数,4个负数和1个零线[总数9]。现在,在我的小提琴中,滴答声的值随着数据不断变化。有时它的情节2滴答或某个时间4.
var data = [["Since Mar 10, 2015",6], ["1 year",2], ["3 year",-10], ["Since Mar 10, 2010",1]];
d3.select("#example")
.datum(data)
.call(columnChart()
.width(320)
.height(240)
.x(function(d, i) { return d[0]; })
.y(function(d, i) { return d[1]; }));
function columnChart() {
var margin = {top: 30, right: 10, bottom: 50, left: 50},
width = 20,
height = 20,
xRoundBands = 0.6,
xValue = function(d) { return d[0]; },
yValue = function(d) { return d[1]; },
xScale = d3.scale.ordinal(),
yScale = d3.scale.linear(),
yAxis = d3.svg.axis().scale(yScale).orient("left"),
xAxis = d3.svg.axis().scale(xScale);
var isNegative = false;
function chart(selection) {
selection.each(function(data) {
// Convert data to standard representation greedily;
// this is needed for nondeterministic accessors.
for(var i=0; i< data.length; i++){
if(data[i][1] < 0){
isNegative = true;
}
}
data = data.map(function(d, i) {
return [xValue.call(data, d, i), yValue.call(data, d, i)];
});
// Update the x-scale.
xScale
.domain(data.map(function(d) { return d[0];} ))
.rangeRoundBands([0, width - margin.left - margin.right], xRoundBands);
var min = d3.min(data, function(d) { return d[1]; });
var max = d3.max(data, function(d) { return d[1]; });
// alert(min);
yScale.domain([d3.min(data, function(d) { return d[1]; }), d3.max(data, function(d) { return d[1]; })])
.range([height - margin.top - margin.bottom, 0])
.nice();
// All Positive
if(min > 0) {
yScale.domain([0, max]);
} else if(max < 0) {
yScale.domain([min, 0]);
}
// Select the svg element, if it exists.
var svg = d3.select(this).selectAll("svg").data([data]);
// Otherwise, create the skeletal chart.
var gEnter = svg.enter().append("svg").append("g");
gEnter.append("g").attr("class", "y axis");
gEnter.append("g").attr("class", "x axis");
gEnter.append("g").attr("class", "x axis zero");
// Update the outer dimensions.
svg .attr("width", width)
.attr("height", height);
// Update the inner dimensions.
var g = svg.select("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Update the y-axis.
g.select(".y.axis")
.call(yAxis.tickSize(0).ticks(5))
.selectAll("g")
.selectAll("text")
.text(function(d){
return d+"%";
});
g.append("g")
.selectAll("line.line")
.data(yScale.ticks(5))
.enter()
.append("line")
.attr(
{
"class":"line grid tick",
"x1" : 0,
"x2" : ( width - 60 ),
"y1" : function(d){ return yScale(d);},
"y2" : function(d){ return yScale(d);},
});
gEnter.append("g").attr("class", "bars");
// Update the bars.
var bar = g.select(".bars")
.selectAll(".bar")
.data(data);
bar.enter().append("rect");
bar.exit().remove();
bar .attr("class", function(d, i) { return d[1] < 0 ? "bar negative" : "bar positive"; })
.attr("x", function(d) { return X(d); })
.attr("y", function(d, i) { return d[1] < 0 ? Y0() : Y(d); })
.attr("width", xScale.rangeBand())
.attr("height", function(d, i) { return Math.abs( Y(d) - Y0() ); });
// x axis at the bottom of the chart
if( isNegative === true ){
var xScaleHeight = height - margin.top - margin.bottom+12;
}else{
var xScaleHeight = height - margin.top - margin.bottom;
}
g.select(".x.axis")
.attr("transform", "translate(0," + ( xScaleHeight ) + ")")
.call(xAxis.orient("bottom"))
.selectAll("text")
.call(wrap, xScale.rangeBand());
// zero line
g.select(".x.axis.zero")
.attr("transform", "translate(0," + Y0() + ")")
.attr("class", "zero axis")
.call(xAxis.tickFormat("").tickSize(0));
// Update the text in bars.
var bar1 = svg.select(".bars").selectAll("text").data(data);
bar1 .data(data)
.enter()
.append("text")
.attr("class", "text")
.text(function(d) { return d[1]+"%"; })
.attr("x", function(d) { return X(d); })
.attr("y", function(d, i) { return d[1] < 0 ? Math.abs(Y(d)+10) : Y(d)-2; });
});
}
// Custom function for text wrap
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1, // ems
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > 55) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
}
}
});
}
// The x-accessor for the path generator; xScale ∘ xValue.
function X(d) {
return xScale(d[0]);
}
function Y0() {
return yScale(0);
}
// The x-accessor for the path generator; yScale ∘ yValue.
function Y(d) {
return yScale(d[1]);
}
chart.margin = function(_) {
if (!arguments.length) return margin;
margin = _;
return chart;
};
chart.width = function(_) {
if (!arguments.length) return width;
width = _;
return chart;
};
chart.height = function(_) {
if (!arguments.length) return height;
height = _;
return chart;
};
chart.x = function(_) {
if (!arguments.length) return xValue;
xValue = _;
return chart;
};
chart.y = function(_) {
if (!arguments.length) return yValue;
yValue = _;
return chart;
};
return chart;
}
提前致谢:)