d3/d3.chart.js

179 строки
4.9 KiB
JavaScript

(function(){d3.chart = {};
// ranges (bad, satisfactory, good)
// measures (actual, forecast)
// markers (previous, goal)
/*
* Chart design based on the recommendations of Stephen Few. Implementation
* based on the work of Clint Ivy, Jamie Love, and Jason Davies.
* http://projects.instantcognition.com/protovis/bulletchart/
*/
/**
* Constructs a new, empty bullet chart.
*/
d3.chart.bullet = function() {
var orient = 'left',
duration = 0,
ranges = function(d) { return d.ranges },
markers = function(d) { return d.markers },
measures = function(d) { return d.measures },
horizontal,
maximum = null,
width = 800,
height = 30,
rangeColor = d3.scale.linear(),
measureColor = d3.scale.linear(),
scale = d3.scale.linear(),
tickFormat = d3.format(',.0f'),
transition = function(x) { return x };
var reverse = function(l) {
for (var i=0, ii=l.length; i<ii; i++) {
l[i].sort(function(a, b) { return b - a });
}
};
var bullet = function(chart) {
var data = [];
for (var i=0, ii=this[0].length; i<ii; i++) {
data.push(this[0][i].__data__);
}
var cache = {
ranges: data.map(ranges),
measures: data.map(measures),
markers: data.map(markers)
};
buildCache(cache);
// sort to lay SVG in correct order
reverse(cache.ranges);
reverse(cache.measures);
chart.selectAll('rect.range')
.data(ranges)
.enter().append('svg:rect')
.attr('class', 'range');
transition(chart.selectAll('rect.range'))
.attr('width', scale)
.attr('height', height)
.attr('fill', function(d, i) { return rangeColor(i) });
chart.selectAll('rect.measure')
.data(measures)
.enter().append('svg:rect')
.attr('class', 'measure');
transition(chart.selectAll('rect.measure'))
.attr('width', scale)
.attr('height', height / 3)
.attr('y', height / 3)
.attr('fill', function(d, i) { return measureColor(i) });
chart.selectAll('line.marker')
.data(markers)
.enter().append('svg:line')
.attr('class', 'marker')
.attr('stroke', '#000')
.attr('stroke-width', '2px')
transition(chart.selectAll('line.marker'))
.attr('x1', scale)
.attr('x2', scale)
.attr('y1', height/6)
.attr('y2', height * 5/6)
var ticks = scale.ticks(10);
var ruleLine = this.selectAll('line.rule')
.data(ticks)
ruleLine.exit().remove();
ruleLine.enter().append('svg:line')
.attr('class', 'rule')
.attr('stroke', '#666')
.attr('stroke-width', '.5px')
transition(chart.selectAll('line.rule'))
.attr('x1', scale)
.attr('x2', scale)
.attr('y1', height)
.attr('y2', height * 7/6)
var tickText = this.selectAll('text.tick')
.data(ticks);
tickText.exit().remove();
tickText.enter().append('svg:text')
.attr('class', 'tick')
.attr('text-anchor', 'middle')
.attr('dy', '1em')
transition(chart.selectAll('text.tick')
.text(tickFormat))
.attr('x', scale)
.attr('y', height * 7/6)
}
var maxlength = function(l) {
return d3.max(l, function(d) { return d.length });
}
/** Cache chart state to optimize properties. */
var buildCache = function(cache) {
horizontal = /^left|right$/.test(orient);
rangeColor.domain([0, Math.max(1, maxlength(cache.ranges) - 1)])
.range(["#eee", "#bbb"]);
measureColor.domain([0, Math.max(1, maxlength(cache.measures) - 1)])
.range(["lightsteelblue", "steelblue"]);
maximum = d3.max([].concat(cache.ranges, cache.markers, cache.measures), function(d) { return d3.max(d) });
scale.domain([0, maximum]).range([0, width]);
};
// left, right, top, bottom
bullet.orient = function(x) {
if (!arguments.length) return orient;
orient = x;
return bullet;
};
bullet.ranges = function(x) {
if (!arguments.length) return ranges;
ranges = x;
return bullet;
};
bullet.markers = function(x) {
if (!arguments.length) return markers;
markers = x;
return bullet;
};
bullet.measures = function(x) {
if (!arguments.length) return measures;
measures = x;
return bullet;
};
bullet.maximum = function(x) {
if (!arguments.length) return maximum;
maximum = x;
return bullet;
};
bullet.width = function(x) {
if (!arguments.length) return width;
width = x;
return bullet;
};
bullet.height = function(x) {
if (!arguments.length) return height;
height = x;
return bullet;
};
bullet.tickFormat = function(x) {
if (!arguments.length) return tickFormat;
tickFormat = x;
return bullet;
};
bullet.duration = function(x) {
if (!arguments.length) return duration;
duration = x;
transition = duration ? function(x) { return x.transition().duration(duration) } :
function(x) { return x };
return bullet;
};
return bullet;
};
})()