Bullet charts: support for "right" orientation.

This commit is contained in:
Jason Davies 2011-04-08 10:53:48 +01:00
Родитель 4aeb42ba43
Коммит 6aba18bc61
4 изменённых файлов: 87 добавлений и 34 удалений

Просмотреть файл

@ -15,7 +15,7 @@ d3.chart.bullet = function() {
ranges = d3_chart_bulletRanges,
markers = d3_chart_bulletMarkers,
measures = d3_chart_bulletMeasures,
width = 800,
width = 500,
height = 30,
x0 = d3.scale.linear().domain([0, Infinity]).range([0, width]),
x1 = d3.scale.linear().range([0, width]),
@ -39,9 +39,15 @@ d3.chart.bullet = function() {
};
});
var reversed = orient === "right" || orient === "bottom";
// Update the x-scale.
x1.domain([0, max]);
var startpos = function(scale) {
return reversed ? function(d) { return width - scale(d); } : 0;
};
// Update the range rects.
var range = chart.selectAll("rect.range")
.data(d3_chart_bulletRanges);
@ -50,12 +56,15 @@ d3.chart.bullet = function() {
.attr("class", function(d, i) { return "range s" + i; })
.attr("width", x0)
.attr("height", height)
.attr("x", startpos(x0))
.transition()
.duration(duration)
.attr("width", x1);
.attr("width", x1)
.attr("x", startpos(x1))
range.transition()
.duration(duration)
.attr("x", startpos(x1))
.attr("width", x1)
.attr("height", height);
@ -67,36 +76,43 @@ d3.chart.bullet = function() {
.attr("class", function(d, i) { return "measure s" + i; })
.attr("width", x0)
.attr("height", height / 3)
.attr("x", startpos(x0))
.attr("y", height / 3)
.transition()
.duration(duration)
.attr("width", x1);
.attr("width", x1)
.attr("x", startpos(x1))
measure.transition()
.duration(duration)
.attr("width", x1)
.attr("height", height / 3)
.attr("x", startpos(x1))
.attr("y", height / 3);
// Update the marker lines.
var marker = chart.selectAll("line.marker")
.data(d3_chart_bulletMarkers);
var pos = function(scale) {
return reversed ? function(d) { return width - scale(d); } : scale;
};
marker.enter().append("svg:line")
.attr("class", "marker")
.attr("x1", x0)
.attr("x2", x0)
.attr("x1", pos(x0))
.attr("x2", pos(x0))
.attr("y1", height / 6)
.attr("y2", height * 5 / 6)
.transition()
.duration(duration)
.attr("x1", x1)
.attr("x2", x1);
.attr("x1", pos(x1))
.attr("x2", pos(x1));
marker.transition()
.duration(duration)
.attr("x1", x1)
.attr("x2", x1)
.attr("x1", pos(x1))
.attr("x2", pos(x1))
.attr("y1", height / 6)
.attr("y2", height * 5 / 6);
@ -104,10 +120,16 @@ d3.chart.bullet = function() {
var tick = chart.selectAll("g.tick")
.data(x1.ticks(10), tickFormat);
var translate = function(f) {
return function(d) {
return "translate(" + f(d) + ",0)";
};
};
// Initialize the ticks with the old scale, x0.
var tickEnter = tick.enter().append("svg:g")
.attr("class", "tick")
.attr("transform", function(d) { return "translate(" + x0(d) + ",0)"; })
.attr("transform", translate(pos(x0)))
.attr("opacity", 1e-6);
tickEnter.append("svg:line")
@ -123,13 +145,13 @@ d3.chart.bullet = function() {
// Transition the entering ticks to the new scale, x1.
tickEnter.transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + x1(d) + ",0)"; })
.attr("transform", translate(pos(x1)))
.attr("opacity", 1);
// Transition the updating ticks to the new scale, x1.
var tickUpdate = tick.transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + x1(d) + ",0)"; })
.attr("transform", translate(pos(x1)))
.attr("opacity", 1);
tickUpdate.select("line")
@ -142,7 +164,7 @@ d3.chart.bullet = function() {
// Transition the exiting ticks to the new scale, x1.
tick.exit().transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + x1(d) + ",0)"; })
.attr("transform", translate(pos(x1)))
.attr("opacity", 1e-6)
.remove();

2
d3.chart.min.js поставляемый
Просмотреть файл

@ -1 +1 @@
(function(){function d(a){return a.data}function c(a){return a.measures}function b(a){return a.markers}function a(a){return a.ranges}d3.chart={},d3.chart.bullet=function(){function o(e){var j=0;e.map(function(a,b){var c=g.call(this,a,b).slice().sort(d3.descending),d=h.call(this,a,b).slice().sort(d3.descending),e=i.call(this,a,b).slice().sort(d3.descending);j=Math.max(j,c[0],d[0],e[0]);return{ranges:c,markers:d,measures:e,data:a}}),m.domain([0,j]);var o=e.selectAll("rect.range").data(a);o.enter().append("svg:rect").attr("class",function(a,b){return"range s"+b}).attr("width",l).attr("height",k).transition().duration(f).attr("width",m),o.transition().duration(f).attr("width",m).attr("height",k);var p=e.selectAll("rect.measure").data(c);p.enter().append("svg:rect").attr("class",function(a,b){return"measure s"+b}).attr("width",l).attr("height",k/3).attr("y",k/3).transition().duration(f).attr("width",m),p.transition().duration(f).attr("width",m).attr("height",k/3).attr("y",k/3);var q=e.selectAll("line.marker").data(b);q.enter().append("svg:line").attr("class","marker").attr("x1",l).attr("x2",l).attr("y1",k/6).attr("y2",k*5/6).transition().duration(f).attr("x1",m).attr("x2",m),q.transition().duration(f).attr("x1",m).attr("x2",m).attr("y1",k/6).attr("y2",k*5/6);var r=e.selectAll("g.tick").data(m.ticks(10),n),s=r.enter().append("svg:g").attr("class","tick").attr("transform",function(a){return"translate("+l(a)+",0)"}).attr("opacity",1e-6);s.append("svg:line").attr("y1",k).attr("y2",k*7/6),s.append("svg:text").attr("text-anchor","middle").attr("dy","1em").attr("y",k*7/6).text(n),s.transition().duration(f).attr("transform",function(a){return"translate("+m(a)+",0)"}).attr("opacity",1);var t=r.transition().duration(f).attr("transform",function(a){return"translate("+m(a)+",0)"}).attr("opacity",1);t.select("line").attr("y1",k).attr("y2",k*7/6),t.select("text").attr("y",k*7/6),r.exit().transition().duration(f).attr("transform",function(a){return"translate("+m(a)+",0)"}).attr("opacity",1e-6).remove(),e.map(d),l.domain([0,j])}var e="left",f=0,g=a,h=b,i=c,j=800,k=30,l=d3.scale.linear().domain([0,Infinity]).range([0,j]),m=d3.scale.linear().range([0,j]),n=d3.format(",.0f");o.orient=function(a){if(!arguments.length)return e;e=a;return o},o.ranges=function(a){if(!arguments.length)return g;g=a;return o},o.markers=function(a){if(!arguments.length)return h;h=a;return o},o.measures=function(a){if(!arguments.length)return i;i=a;return o},o.width=function(a){if(!arguments.length)return j;l.range([0,j=a]),m.range([0,j]);return o},o.height=function(a){if(!arguments.length)return k;k=a;return o},o.tickFormat=function(a){if(!arguments.length)return n;n=a;return o},o.duration=function(a){if(!arguments.length)return f;f=a;return o};return o}})()
(function(){function d(a){return a.data}function c(a){return a.measures}function b(a){return a.markers}function a(a){return a.ranges}d3.chart={},d3.chart.bullet=function(){function o(o){var p=0;o.map(function(a,b){var c=g.call(this,a,b).slice().sort(d3.descending),d=h.call(this,a,b).slice().sort(d3.descending),e=i.call(this,a,b).slice().sort(d3.descending);p=Math.max(p,c[0],d[0],e[0]);return{ranges:c,markers:d,measures:e,data:a}});var q=e==="right"||e==="bottom";m.domain([0,p]);var r=function(a){return q?function(b){return j-a(b)}:0},s=o.selectAll("rect.range").data(a);s.enter().append("svg:rect").attr("class",function(a,b){return"range s"+b}).attr("width",l).attr("height",k).attr("x",r(l)).transition().duration(f).attr("width",m).attr("x",r(m)),s.transition().duration(f).attr("x",r(m)).attr("width",m).attr("height",k);var t=o.selectAll("rect.measure").data(c);t.enter().append("svg:rect").attr("class",function(a,b){return"measure s"+b}).attr("width",l).attr("height",k/3).attr("x",r(l)).attr("y",k/3).transition().duration(f).attr("width",m).attr("x",r(m)),t.transition().duration(f).attr("width",m).attr("height",k/3).attr("x",r(m)).attr("y",k/3);var u=o.selectAll("line.marker").data(b),v=function(a){return q?function(b){return j-a(b)}:a};u.enter().append("svg:line").attr("class","marker").attr("x1",v(l)).attr("x2",v(l)).attr("y1",k/6).attr("y2",k*5/6).transition().duration(f).attr("x1",v(m)).attr("x2",v(m)),u.transition().duration(f).attr("x1",v(m)).attr("x2",v(m)).attr("y1",k/6).attr("y2",k*5/6);var w=o.selectAll("g.tick").data(m.ticks(10),n),x=function(a){return function(b){return"translate("+a(b)+",0)"}},y=w.enter().append("svg:g").attr("class","tick").attr("transform",x(v(l))).attr("opacity",1e-6);y.append("svg:line").attr("y1",k).attr("y2",k*7/6),y.append("svg:text").attr("text-anchor","middle").attr("dy","1em").attr("y",k*7/6).text(n),y.transition().duration(f).attr("transform",x(v(m))).attr("opacity",1);var z=w.transition().duration(f).attr("transform",x(v(m))).attr("opacity",1);z.select("line").attr("y1",k).attr("y2",k*7/6),z.select("text").attr("y",k*7/6),w.exit().transition().duration(f).attr("transform",x(v(m))).attr("opacity",1e-6).remove(),o.map(d),l.domain([0,p])}var e="left",f=0,g=a,h=b,i=c,j=500,k=30,l=d3.scale.linear().domain([0,Infinity]).range([0,j]),m=d3.scale.linear().range([0,j]),n=d3.format(",.0f");o.orient=function(a){if(!arguments.length)return e;e=a;return o},o.ranges=function(a){if(!arguments.length)return g;g=a;return o},o.markers=function(a){if(!arguments.length)return h;h=a;return o},o.measures=function(a){if(!arguments.length)return i;i=a;return o},o.width=function(a){if(!arguments.length)return j;l.range([0,j=a]),m.range([0,j]);return o},o.height=function(a){if(!arguments.length)return k;k=a;return o},o.tickFormat=function(a){if(!arguments.length)return n;n=a;return o},o.duration=function(a){if(!arguments.length)return f;f=a;return o};return o}})()

Просмотреть файл

@ -10,12 +10,20 @@
<body>
<script type="text/javascript">
var bullet = d3.chart.bullet()
.orient("left")
.duration(1000);
var bullet = function(chart) {
chart.each(function(orient) {
var bulletChart = d3.chart.bullet()
.orient(orient).duration(1000);
// Is there a simpler way to construct a group from the current node?
chart.filter(function(d) { return d === orient })
.selectAll('g.bullet').call(bulletChart);
});
};
var vis = d3.select("body").append("svg:svg")
.attr("width", 900)
var vis = d3.select("body").selectAll('svg')
.data(['left', 'right', 'top', 'bottom'])
.enter().append("svg:svg")
.attr("width", 520)
.attr("height", 300)
.append("svg:g")
.attr("transform", "translate(10,0)");
@ -25,7 +33,8 @@ vis.selectAll("g.bullet")
.enter().append("svg:g")
.attr("class", "bullet")
.attr("transform", function(d, i) { return "translate(0," + (i * 60) + ")"; })
.call(bullet);
vis.call(bullet);
function randomize() {
for (var i = 0, ii = bullets.length; i < ii; i++) {
@ -34,7 +43,7 @@ function randomize() {
b.markers = b.markers.map(function(d) { return Math.random() * 1000; });
b.measures = b.measures.map(function(d) { return Math.random() * 1000; });
}
vis.selectAll("g.bullet").call(bullet);
vis.call(bullet);
}
</script>

Просмотреть файл

@ -14,7 +14,7 @@ d3.chart.bullet = function() {
ranges = d3_chart_bulletRanges,
markers = d3_chart_bulletMarkers,
measures = d3_chart_bulletMeasures,
width = 800,
width = 500,
height = 30,
x0 = d3.scale.linear().domain([0, Infinity]).range([0, width]),
x1 = d3.scale.linear().range([0, width]),
@ -38,9 +38,15 @@ d3.chart.bullet = function() {
};
});
var reversed = orient === "right" || orient === "bottom";
// Update the x-scale.
x1.domain([0, max]);
var startpos = function(scale) {
return reversed ? function(d) { return width - scale(d); } : 0;
};
// Update the range rects.
var range = chart.selectAll("rect.range")
.data(d3_chart_bulletRanges);
@ -49,12 +55,15 @@ d3.chart.bullet = function() {
.attr("class", function(d, i) { return "range s" + i; })
.attr("width", x0)
.attr("height", height)
.attr("x", startpos(x0))
.transition()
.duration(duration)
.attr("width", x1);
.attr("width", x1)
.attr("x", startpos(x1))
range.transition()
.duration(duration)
.attr("x", startpos(x1))
.attr("width", x1)
.attr("height", height);
@ -66,36 +75,43 @@ d3.chart.bullet = function() {
.attr("class", function(d, i) { return "measure s" + i; })
.attr("width", x0)
.attr("height", height / 3)
.attr("x", startpos(x0))
.attr("y", height / 3)
.transition()
.duration(duration)
.attr("width", x1);
.attr("width", x1)
.attr("x", startpos(x1))
measure.transition()
.duration(duration)
.attr("width", x1)
.attr("height", height / 3)
.attr("x", startpos(x1))
.attr("y", height / 3);
// Update the marker lines.
var marker = chart.selectAll("line.marker")
.data(d3_chart_bulletMarkers);
var pos = function(scale) {
return reversed ? function(d) { return width - scale(d); } : scale;
};
marker.enter().append("svg:line")
.attr("class", "marker")
.attr("x1", x0)
.attr("x2", x0)
.attr("x1", pos(x0))
.attr("x2", pos(x0))
.attr("y1", height / 6)
.attr("y2", height * 5 / 6)
.transition()
.duration(duration)
.attr("x1", x1)
.attr("x2", x1);
.attr("x1", pos(x1))
.attr("x2", pos(x1));
marker.transition()
.duration(duration)
.attr("x1", x1)
.attr("x2", x1)
.attr("x1", pos(x1))
.attr("x2", pos(x1))
.attr("y1", height / 6)
.attr("y2", height * 5 / 6);
@ -103,10 +119,16 @@ d3.chart.bullet = function() {
var tick = chart.selectAll("g.tick")
.data(x1.ticks(10), tickFormat);
var translate = function(f) {
return function(d) {
return "translate(" + f(d) + ",0)";
};
};
// Initialize the ticks with the old scale, x0.
var tickEnter = tick.enter().append("svg:g")
.attr("class", "tick")
.attr("transform", function(d) { return "translate(" + x0(d) + ",0)"; })
.attr("transform", translate(pos(x0)))
.attr("opacity", 1e-6);
tickEnter.append("svg:line")
@ -122,13 +144,13 @@ d3.chart.bullet = function() {
// Transition the entering ticks to the new scale, x1.
tickEnter.transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + x1(d) + ",0)"; })
.attr("transform", translate(pos(x1)))
.attr("opacity", 1);
// Transition the updating ticks to the new scale, x1.
var tickUpdate = tick.transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + x1(d) + ",0)"; })
.attr("transform", translate(pos(x1)))
.attr("opacity", 1);
tickUpdate.select("line")
@ -141,7 +163,7 @@ d3.chart.bullet = function() {
// Transition the exiting ticks to the new scale, x1.
tick.exit().transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + x1(d) + ",0)"; })
.attr("transform", translate(pos(x1)))
.attr("opacity", 1e-6)
.remove();