d3/d3.chart.js

179 строки
4.9 KiB
JavaScript
Исходник Обычный вид История

2011-04-07 20:54:03 +04:00
(function(){d3.chart = {};
2011-04-06 22:47:55 +04:00
// 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/
*/
/**
2011-04-07 20:54:03 +04:00
* Constructs a new, empty bullet chart.
2011-04-06 22:47:55 +04:00
*/
2011-04-07 20:54:03 +04:00
d3.chart.bullet = function() {
2011-04-06 22:47:55 +04:00
var orient = 'left',
duration = 0,
ranges = function(d) { return d.ranges },
markers = function(d) { return d.markers },
measures = function(d) { return d.measures },
2011-04-06 22:47:55 +04:00
horizontal,
maximum = null,
2011-04-07 22:32:48 +04:00
width = 800,
height = 30,
2011-04-06 22:47:55 +04:00
rangeColor = d3.scale.linear(),
measureColor = d3.scale.linear(),
scale = d3.scale.linear(),
2011-04-08 01:38:50 +04:00
tickFormat = d3.format(',.0f'),
transition = function(x) { return x };
2011-04-06 22:47:55 +04:00
var reverse = function(l) {
for (var i=0, ii=l.length; i<ii; i++) {
l[i].sort(function(a, b) { return b - a });
}
2011-04-06 23:18:04 +04:00
};
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')
2011-04-07 22:32:48 +04:00
.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')
2011-04-07 22:32:48 +04:00
.attr('class', 'measure');
transition(chart.selectAll('rect.measure'))
.attr('width', scale)
.attr('height', height / 3)
.attr('y', height / 3)
2011-04-06 22:47:55 +04:00
.attr('fill', function(d, i) { return measureColor(i) });
chart.selectAll('line.marker')
.data(markers)
.enter().append('svg:line')
2011-04-06 22:47:55 +04:00
.attr('class', 'marker')
2011-04-07 22:32:48 +04:00
.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);
2011-04-07 22:32:48 +04:00
var ruleLine = this.selectAll('line.rule')
.data(ticks)
ruleLine.exit().remove();
ruleLine.enter().append('svg:line')
.attr('class', 'rule')
2011-04-07 22:32:48 +04:00
.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)
2011-04-07 22:32:48 +04:00
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))
2011-04-07 22:32:48 +04:00
.attr('x', scale)
.attr('y', height * 7/6)
2011-04-06 22:47:55 +04:00
}
var maxlength = function(l) {
return d3.max(l, function(d) { return d.length });
}
2011-04-07 20:54:03 +04:00
/** Cache chart state to optimize properties. */
var buildCache = function(cache) {
2011-04-06 22:47:55 +04:00
horizontal = /^left|right$/.test(orient);
rangeColor.domain([0, Math.max(1, maxlength(cache.ranges) - 1)])
2011-04-06 22:47:55 +04:00
.range(["#eee", "#bbb"]);
measureColor.domain([0, Math.max(1, maxlength(cache.measures) - 1)])
2011-04-06 22:47:55 +04:00
.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]);
2011-04-06 22:47:55 +04:00
};
// 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;
2011-04-08 01:38:50 +04:00
transition = duration ? function(x) { return x.transition().duration(duration) } :
function(x) { return x };
return bullet;
};
2011-04-06 22:47:55 +04:00
return bullet;
};
2011-04-07 20:54:03 +04:00
})()