Extract title & subtitle from bullet chart.

It's nice, but I think it's a bit more flexible to not have it as part of the
chart specification. This way, people can define titles however they like. It
might be nice to take a similar approach with reference ticks in the future.
This commit is contained in:
Michael Bostock 2011-04-08 14:40:29 -07:00
Родитель e1399b1182
Коммит 33260423a3
6 изменённых файлов: 172 добавлений и 184 удалений

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

@ -12,19 +12,17 @@
d3.chart.bullet = function() {
var orient = "left",
duration = 0,
title = d3_chart_bulletTitle,
subtitle = d3_chart_bulletSubtitle,
ranges = d3_chart_bulletRanges,
markers = d3_chart_bulletMarkers,
measures = d3_chart_bulletMeasures,
width = 380,
height = 30,
x0 = null,
x1 = d3.scale.linear(),
x0,
tickFormat = d3.format(",.0f");
function bullet(g) {
var max = 0;
var max = 0,
reverse = orient == "right" || orient == "bottom";
// Convert the data to a standardized representation, and also compute the
// maximum value, needed to standardize the x-scale across multiples.
@ -34,8 +32,6 @@ d3.chart.bullet = function() {
z = measures.call(this, d, i).slice().sort(d3.descending);
max = Math.max(max, r[0], m[0], z[0]);
return {
title: [title.call(this, d, i)],
subtitle: [subtitle.call(this, d, i)],
ranges: r,
markers: m,
measures: z,
@ -43,87 +39,64 @@ d3.chart.bullet = function() {
};
});
var reversed = orient === "right" || orient === "bottom";
// Update the x-scales.
var xRange = reversed ? [width, 0] : [0, width];
x1.domain([0, max]).range(xRange);
if (x0 === null)
x0 = d3.scale.linear().domain([0, Infinity]).range(xRange);
var x1 = d3.scale.linear()
.domain([0, max])
.range(reverse ? [width, 0] : [0, width]);
// Update the title.
var titleText = g.select("text.title");
// Initialize the old scale, if this is the first render.
if (!x0) x0 = d3.scale.linear()
.domain([0, Infinity])
.range(x1.range());
if (titleText.empty())
titleText = g.append("svg:text")
.attr("class", "title")
.attr("dy", "1em")
.style("font-weight", "bold");
titleText
.text(d3_chart_bulletTitle);
// Update the subtitle.
var subtitleText = g.select("text.subtitle");
if (subtitleText.empty())
subtitleText = g.append("svg:text")
.attr("class", "subtitle")
.attr("dy", "2.5em")
.style("font-size", ".7em")
.style("fill", "#999");
subtitleText
.text(d3_chart_bulletSubtitle);
// Update the chart.
var chart = g.select("g.chart");
if (chart.empty())
chart = g.append("svg:g")
.attr("class", "chart")
.attr("transform", "translate(120)");
// Derive width-scales from the x-scales.
var w0 = d3_chart_bulletWidth(x0),
w1 = d3_chart_bulletWidth(x1);
// Update the range rects.
var range = chart.selectAll("rect.range")
var range = g.selectAll("rect.range")
.data(d3_chart_bulletRanges);
range.enter().append("svg:rect")
.attr("class", function(d, i) { return "range s" + i; })
.attr("width", function(d) { return Math.abs(x0(d) - x0(0)); })
.attr("width", w0)
.attr("height", height)
.attr("x", reversed ? x0 : 0)
.attr("x", reverse ? x0 : 0)
.transition()
.duration(duration)
.attr("width", function(d) { return Math.abs(x1(d) - x1(0)); })
.attr("x", reversed ? x1 : 0);
.attr("width", w1)
.attr("x", reverse ? x1 : 0);
range.transition()
.duration(duration)
.attr("x", reversed ? x1 : 0)
.attr("width", function(d) { return Math.abs(x1(d) - x1(0)); })
.attr("x", reverse ? x1 : 0)
.attr("width", w1)
.attr("height", height);
// Update the measure rects.
var measure = chart.selectAll("rect.measure")
var measure = g.selectAll("rect.measure")
.data(d3_chart_bulletMeasures);
measure.enter().append("svg:rect")
.attr("class", function(d, i) { return "measure s" + i; })
.attr("width", function(d) { return Math.abs(x0(d) - x0(0)); })
.attr("width", w0)
.attr("height", height / 3)
.attr("x", reversed ? x0 : 0)
.attr("x", reverse ? x0 : 0)
.attr("y", height / 3)
.transition()
.duration(duration)
.attr("width", function(d) { return Math.abs(x1(d) - x1(0)); })
.attr("x", reversed ? x1 : 0);
.attr("width", w1)
.attr("x", reverse ? x1 : 0);
measure.transition()
.duration(duration)
.attr("width", function(d) { return Math.abs(x1(d) - x1(0)); })
.attr("width", w1)
.attr("height", height / 3)
.attr("x", reversed ? x1 : 0)
.attr("x", reverse ? x1 : 0)
.attr("y", height / 3);
// Update the marker lines.
var marker = chart.selectAll("line.marker")
var marker = g.selectAll("line.marker")
.data(d3_chart_bulletMarkers);
marker.enter().append("svg:line")
@ -145,19 +118,13 @@ d3.chart.bullet = function() {
.attr("y2", height * 5 / 6);
// Update the tick groups.
var tick = chart.selectAll("g.tick")
var tick = g.selectAll("g.tick")
.data(x1.ticks(8), tickFormat);
var translate = function(f) {
return function(d) {
return "translate(" + f(d) + ")";
};
};
// Initialize the ticks with the old scale, x0.
var tickEnter = tick.enter().append("svg:g")
.attr("class", "tick")
.attr("transform", translate(x0))
.attr("transform", d3_chart_bulletTranslate(x0))
.attr("opacity", 1e-6);
tickEnter.append("svg:line")
@ -173,13 +140,13 @@ d3.chart.bullet = function() {
// Transition the entering ticks to the new scale, x1.
tickEnter.transition()
.duration(duration)
.attr("transform", translate(x1))
.attr("transform", d3_chart_bulletTranslate(x1))
.attr("opacity", 1);
// Transition the updating ticks to the new scale, x1.
var tickUpdate = tick.transition()
.duration(duration)
.attr("transform", translate(x1))
.attr("transform", d3_chart_bulletTranslate(x1))
.attr("opacity", 1);
tickUpdate.select("line")
@ -192,13 +159,13 @@ d3.chart.bullet = function() {
// Transition the exiting ticks to the new scale, x1.
tick.exit().transition()
.duration(duration)
.attr("transform", translate(x1))
.attr("transform", d3_chart_bulletTranslate(x1))
.attr("opacity", 1e-6)
.remove();
// Lastly, restore the original data and update the previous scale!
g.map(d3_chart_bulletData);
x0.domain([0, max]).range(xRange);
x0 = x1;
}
// left, right, top, bottom
@ -228,8 +195,7 @@ d3.chart.bullet = function() {
bullet.width = function(x) {
if (!arguments.length) return width;
x0.range([0, width = x]);
x1.range([0, width]);
width = x;
return bullet;
};
@ -254,14 +220,6 @@ d3.chart.bullet = function() {
return bullet;
};
function d3_chart_bulletTitle(d) {
return d.title;
}
function d3_chart_bulletSubtitle(d) {
return d.subtitle;
}
function d3_chart_bulletRanges(d) {
return d.ranges;
}
@ -277,4 +235,17 @@ function d3_chart_bulletMeasures(d) {
function d3_chart_bulletData(d) {
return d.data;
}
function d3_chart_bulletTranslate(x) {
return function(d) {
return "translate(" + x(d) + ",0)";
};
}
function d3_chart_bulletWidth(x) {
var x0 = x(0);
return function(d) {
return Math.abs(x(d) - x0);
};
}
})()

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

@ -1 +1 @@
(function(){function f(a){return a.data}function e(a){return a.measures}function d(a){return a.markers}function c(a){return a.ranges}function b(a){return a.subtitle}function a(a){return a.title}d3.chart={},d3.chart.bullet=function(){function s(s){var t=0;s.map(function(a,b){var c=k.call(this,a,b).slice().sort(d3.descending),d=l.call(this,a,b).slice().sort(d3.descending),e=m.call(this,a,b).slice().sort(d3.descending);t=Math.max(t,c[0],d[0],e[0]);return{title:[i.call(this,a,b)],subtitle:[j.call(this,a,b)],ranges:c,markers:d,measures:e,data:a}});var u=g==="right"||g==="bottom",v=u?[n,0]:[0,n];q.domain([0,t]).range(v),p===null&&(p=d3.scale.linear().domain([0,Infinity]).range(v));var w=s.select("text.title");w.empty()&&(w=s.append("svg:text").attr("class","title").attr("dy","1em").style("font-weight","bold")),w.text(a);var x=s.select("text.subtitle");x.empty()&&(x=s.append("svg:text").attr("class","subtitle").attr("dy","2.5em").style("font-size",".7em").style("fill","#999")),x.text(b);var y=s.select("g.chart");y.empty()&&(y=s.append("svg:g").attr("class","chart").attr("transform","translate(120)"));var z=y.selectAll("rect.range").data(c);z.enter().append("svg:rect").attr("class",function(a,b){return"range s"+b}).attr("width",function(a){return Math.abs(p(a)-p(0))}).attr("height",o).attr("x",u?p:0).transition().duration(h).attr("width",function(a){return Math.abs(q(a)-q(0))}).attr("x",u?q:0),z.transition().duration(h).attr("x",u?q:0).attr("width",function(a){return Math.abs(q(a)-q(0))}).attr("height",o);var A=y.selectAll("rect.measure").data(e);A.enter().append("svg:rect").attr("class",function(a,b){return"measure s"+b}).attr("width",function(a){return Math.abs(p(a)-p(0))}).attr("height",o/3).attr("x",u?p:0).attr("y",o/3).transition().duration(h).attr("width",function(a){return Math.abs(q(a)-q(0))}).attr("x",u?q:0),A.transition().duration(h).attr("width",function(a){return Math.abs(q(a)-q(0))}).attr("height",o/3).attr("x",u?q:0).attr("y",o/3);var B=y.selectAll("line.marker").data(d);B.enter().append("svg:line").attr("class","marker").attr("x1",p).attr("x2",p).attr("y1",o/6).attr("y2",o*5/6).transition().duration(h).attr("x1",q).attr("x2",q),B.transition().duration(h).attr("x1",q).attr("x2",q).attr("y1",o/6).attr("y2",o*5/6);var C=y.selectAll("g.tick").data(q.ticks(8),r),D=function(a){return function(b){return"translate("+a(b)+")"}},E=C.enter().append("svg:g").attr("class","tick").attr("transform",D(p)).attr("opacity",1e-6);E.append("svg:line").attr("y1",o).attr("y2",o*7/6),E.append("svg:text").attr("text-anchor","middle").attr("dy","1em").attr("y",o*7/6).text(r),E.transition().duration(h).attr("transform",D(q)).attr("opacity",1);var F=C.transition().duration(h).attr("transform",D(q)).attr("opacity",1);F.select("line").attr("y1",o).attr("y2",o*7/6),F.select("text").attr("y",o*7/6),C.exit().transition().duration(h).attr("transform",D(q)).attr("opacity",1e-6).remove(),s.map(f),p.domain([0,t]).range(v)}var g="left",h=0,i=a,j=b,k=c,l=d,m=e,n=380,o=30,p=null,q=d3.scale.linear(),r=d3.format(",.0f");s.orient=function(a){if(!arguments.length)return g;g=a;return s},s.ranges=function(a){if(!arguments.length)return k;k=a;return s},s.markers=function(a){if(!arguments.length)return l;l=a;return s},s.measures=function(a){if(!arguments.length)return m;m=a;return s},s.width=function(a){if(!arguments.length)return n;p.range([0,n=a]),q.range([0,n]);return s},s.height=function(a){if(!arguments.length)return o;o=a;return s},s.tickFormat=function(a){if(!arguments.length)return r;r=a;return s},s.duration=function(a){if(!arguments.length)return h;h=a;return s};return s}})()
(function(){function f(a){var b=a(0);return function(c){return Math.abs(a(c)-b)}}function e(a){return function(b){return"translate("+a(b)+",0)"}}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 p(p){var q=0,r=g=="right"||g=="bottom";p.map(function(a,b){var c=i.call(this,a,b).slice().sort(d3.descending),d=j.call(this,a,b).slice().sort(d3.descending),e=k.call(this,a,b).slice().sort(d3.descending);q=Math.max(q,c[0],d[0],e[0]);return{ranges:c,markers:d,measures:e,data:a}});var s=d3.scale.linear().domain([0,q]).range(r?[l,0]:[0,l]);n||(n=d3.scale.linear().domain([0,Infinity]).range(s.range()));var t=f(n),u=f(s),v=p.selectAll("rect.range").data(a);v.enter().append("svg:rect").attr("class",function(a,b){return"range s"+b}).attr("width",t).attr("height",m).attr("x",r?n:0).transition().duration(h).attr("width",u).attr("x",r?s:0),v.transition().duration(h).attr("x",r?s:0).attr("width",u).attr("height",m);var w=p.selectAll("rect.measure").data(c);w.enter().append("svg:rect").attr("class",function(a,b){return"measure s"+b}).attr("width",t).attr("height",m/3).attr("x",r?n:0).attr("y",m/3).transition().duration(h).attr("width",u).attr("x",r?s:0),w.transition().duration(h).attr("width",u).attr("height",m/3).attr("x",r?s:0).attr("y",m/3);var x=p.selectAll("line.marker").data(b);x.enter().append("svg:line").attr("class","marker").attr("x1",n).attr("x2",n).attr("y1",m/6).attr("y2",m*5/6).transition().duration(h).attr("x1",s).attr("x2",s),x.transition().duration(h).attr("x1",s).attr("x2",s).attr("y1",m/6).attr("y2",m*5/6);var y=p.selectAll("g.tick").data(s.ticks(8),o),z=y.enter().append("svg:g").attr("class","tick").attr("transform",e(n)).attr("opacity",1e-6);z.append("svg:line").attr("y1",m).attr("y2",m*7/6),z.append("svg:text").attr("text-anchor","middle").attr("dy","1em").attr("y",m*7/6).text(o),z.transition().duration(h).attr("transform",e(s)).attr("opacity",1);var A=y.transition().duration(h).attr("transform",e(s)).attr("opacity",1);A.select("line").attr("y1",m).attr("y2",m*7/6),A.select("text").attr("y",m*7/6),y.exit().transition().duration(h).attr("transform",e(s)).attr("opacity",1e-6).remove(),p.map(d),n=s}var g="left",h=0,i=a,j=b,k=c,l=380,m=30,n,o=d3.format(",.0f");p.orient=function(a){if(!arguments.length)return g;g=a;return p},p.ranges=function(a){if(!arguments.length)return i;i=a;return p},p.markers=function(a){if(!arguments.length)return j;j=a;return p},p.measures=function(a){if(!arguments.length)return k;k=a;return p},p.width=function(a){if(!arguments.length)return l;l=a;return p},p.height=function(a){if(!arguments.length)return m;m=a;return p},p.tickFormat=function(a){if(!arguments.length)return o;o=a;return p},p.duration=function(a){if(!arguments.length)return h;h=a;return p};return p}})()

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

@ -8,42 +8,65 @@
<link type="text/css" rel="stylesheet" href="bullet.css"/>
</head>
<body>
<input type="button" value="Randomize!" onclick="randomize()"><br>
<script type="text/javascript">
var bullet = function(orient) {
d3.select(this).selectAll("g.bullet")
.call(d3.chart.bullet()
.orient(orient)
.duration(1000));
};
var w = 500,
h = 50,
m = [5, 40, 20, 120]; // top right bottom left
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)");
var bullet = d3.chart.bullet()
.width(w - m[1] - m[3])
.height(h - m[0] - m[2])
.duration(1000);
vis.selectAll("g.bullet")
var vis = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h * bullets.length);
var g = vis.selectAll("g.bullet")
.data(bullets)
.enter().append("svg:g")
.attr("class", "bullet")
.attr("transform", function(d, i) { return "translate(0," + (i * 60) + ")"; })
.attr("transform", function(d, i) {
return "translate(" + m[3] + "," + (i * h + m[0]) + ")";
});
vis.each(bullet);
g.append("svg:text")
.attr("class", "title")
.attr("text-anchor", "end")
.attr("dx", "-6")
.attr("y", bullet.height() / 2)
.text(function(d) { return d.title; });
g.append("svg:text")
.attr("class", "subtitle")
.attr("text-anchor", "end")
.attr("dx", "-6")
.attr("dy", "1em")
.attr("y", bullet.height() / 2)
.text(function(d) { return d.subtitle; });
vis.each(refresh);
function refresh() {
d3.select(this).selectAll("g.bullet").call(bullet);
}
function randomize() {
for (var i = 0, ii = bullets.length; i < ii; i++) {
var b = bullets[i];
b.ranges = b.ranges.map(function(d) { return Math.random() * 1000; });
b.markers = b.markers.map(function(d) { return Math.random() * 1000; });
b.measures = b.measures.map(function(d) { return Math.random() * 1000; });
for (var i = -1, n = bullets.length, b; ++i < n;) {
b = bullets[i];
b.ranges = b.ranges.map(random);
b.markers = b.markers.map(random);
b.measures = b.measures.map(random);
}
vis.each(bullet);
vis.each(refresh);
}
function random() {
return Math.random() * 1000;
}
</script>
<input type="button" value="Randomize!" onclick="randomize()">
</body>
</html>

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

@ -1,8 +1,10 @@
.bullet { font: 10px sans-serif; }
.bullet .marker { stroke: #000; stroke-width: 2px; }
.bullet .tick text { font: 10px sans-serif; }
.bullet .tick line { stroke: #666; stroke-width: .5px; }
.bullet .range.s0 { fill: #eee; }
.bullet .range.s1 { fill: #ddd; }
.bullet .range.s2 { fill: #ccc; }
.bullet .measure.s0 { fill: lightsteelblue; }
.bullet .measure.s1 { fill: steelblue; }
.bullet .title { font-size: 14px; font-weight: bold; }
.bullet .subtitle { fill: #999; }

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

@ -9,15 +9,20 @@
<body>
<script>
var w = 500,
h = 50,
m = [5, 40, 20, 120]; // top right bottom left
var bullet = d3.chart.bullet()
.orient("left")
.tickFormat(function(d) { return d / 1e6; });
.width(w - m[1] - m[3])
.height(h - m[0] - m[2])
.tickFormat(function(d) { return (d / 1e6).toFixed(1); });
var vis = d3.select("body").append("svg:svg")
.attr("width", 800)
.attr("height", 300);
.attr("width", w)
.attr("height", h);
vis.append("svg:g")
var g = vis.append("svg:g")
.data([{
title: "Revenue",
subtitle: "US$, in millions",
@ -26,8 +31,24 @@ vis.append("svg:g")
markers: [1.15e6, 3.0e6]
}])
.attr("class", "bullet")
.attr("transform", "translate(" + m[3] + "," + m[0] + ")")
.call(bullet);
g.append("svg:text")
.attr("class", "title")
.attr("text-anchor", "end")
.attr("dx", "-6")
.attr("y", bullet.height() / 2)
.text(function(d) { return d.title; });
g.append("svg:text")
.attr("class", "subtitle")
.attr("text-anchor", "end")
.attr("dx", "-6")
.attr("dy", "1em")
.attr("y", bullet.height() / 2)
.text(function(d) { return d.subtitle; });
</script>
</body>
</html>

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

@ -11,19 +11,17 @@
d3.chart.bullet = function() {
var orient = "left",
duration = 0,
title = d3_chart_bulletTitle,
subtitle = d3_chart_bulletSubtitle,
ranges = d3_chart_bulletRanges,
markers = d3_chart_bulletMarkers,
measures = d3_chart_bulletMeasures,
width = 380,
height = 30,
x0 = null,
x1 = d3.scale.linear(),
x0,
tickFormat = d3.format(",.0f");
function bullet(g) {
var max = 0;
var max = 0,
reverse = orient == "right" || orient == "bottom";
// Convert the data to a standardized representation, and also compute the
// maximum value, needed to standardize the x-scale across multiples.
@ -33,8 +31,6 @@ d3.chart.bullet = function() {
z = measures.call(this, d, i).slice().sort(d3.descending);
max = Math.max(max, r[0], m[0], z[0]);
return {
title: [title.call(this, d, i)],
subtitle: [subtitle.call(this, d, i)],
ranges: r,
markers: m,
measures: z,
@ -42,87 +38,64 @@ d3.chart.bullet = function() {
};
});
var reversed = orient === "right" || orient === "bottom";
// Update the x-scales.
var xRange = reversed ? [width, 0] : [0, width];
x1.domain([0, max]).range(xRange);
if (x0 === null)
x0 = d3.scale.linear().domain([0, Infinity]).range(xRange);
var x1 = d3.scale.linear()
.domain([0, max])
.range(reverse ? [width, 0] : [0, width]);
// Update the title.
var titleText = g.select("text.title");
// Initialize the old scale, if this is the first render.
if (!x0) x0 = d3.scale.linear()
.domain([0, Infinity])
.range(x1.range());
if (titleText.empty())
titleText = g.append("svg:text")
.attr("class", "title")
.attr("dy", "1em")
.style("font-weight", "bold");
titleText
.text(d3_chart_bulletTitle);
// Update the subtitle.
var subtitleText = g.select("text.subtitle");
if (subtitleText.empty())
subtitleText = g.append("svg:text")
.attr("class", "subtitle")
.attr("dy", "2.5em")
.style("font-size", ".7em")
.style("fill", "#999");
subtitleText
.text(d3_chart_bulletSubtitle);
// Update the chart.
var chart = g.select("g.chart");
if (chart.empty())
chart = g.append("svg:g")
.attr("class", "chart")
.attr("transform", "translate(120)");
// Derive width-scales from the x-scales.
var w0 = d3_chart_bulletWidth(x0),
w1 = d3_chart_bulletWidth(x1);
// Update the range rects.
var range = chart.selectAll("rect.range")
var range = g.selectAll("rect.range")
.data(d3_chart_bulletRanges);
range.enter().append("svg:rect")
.attr("class", function(d, i) { return "range s" + i; })
.attr("width", function(d) { return Math.abs(x0(d) - x0(0)); })
.attr("width", w0)
.attr("height", height)
.attr("x", reversed ? x0 : 0)
.attr("x", reverse ? x0 : 0)
.transition()
.duration(duration)
.attr("width", function(d) { return Math.abs(x1(d) - x1(0)); })
.attr("x", reversed ? x1 : 0);
.attr("width", w1)
.attr("x", reverse ? x1 : 0);
range.transition()
.duration(duration)
.attr("x", reversed ? x1 : 0)
.attr("width", function(d) { return Math.abs(x1(d) - x1(0)); })
.attr("x", reverse ? x1 : 0)
.attr("width", w1)
.attr("height", height);
// Update the measure rects.
var measure = chart.selectAll("rect.measure")
var measure = g.selectAll("rect.measure")
.data(d3_chart_bulletMeasures);
measure.enter().append("svg:rect")
.attr("class", function(d, i) { return "measure s" + i; })
.attr("width", function(d) { return Math.abs(x0(d) - x0(0)); })
.attr("width", w0)
.attr("height", height / 3)
.attr("x", reversed ? x0 : 0)
.attr("x", reverse ? x0 : 0)
.attr("y", height / 3)
.transition()
.duration(duration)
.attr("width", function(d) { return Math.abs(x1(d) - x1(0)); })
.attr("x", reversed ? x1 : 0);
.attr("width", w1)
.attr("x", reverse ? x1 : 0);
measure.transition()
.duration(duration)
.attr("width", function(d) { return Math.abs(x1(d) - x1(0)); })
.attr("width", w1)
.attr("height", height / 3)
.attr("x", reversed ? x1 : 0)
.attr("x", reverse ? x1 : 0)
.attr("y", height / 3);
// Update the marker lines.
var marker = chart.selectAll("line.marker")
var marker = g.selectAll("line.marker")
.data(d3_chart_bulletMarkers);
marker.enter().append("svg:line")
@ -144,19 +117,13 @@ d3.chart.bullet = function() {
.attr("y2", height * 5 / 6);
// Update the tick groups.
var tick = chart.selectAll("g.tick")
var tick = g.selectAll("g.tick")
.data(x1.ticks(8), tickFormat);
var translate = function(f) {
return function(d) {
return "translate(" + f(d) + ")";
};
};
// Initialize the ticks with the old scale, x0.
var tickEnter = tick.enter().append("svg:g")
.attr("class", "tick")
.attr("transform", translate(x0))
.attr("transform", d3_chart_bulletTranslate(x0))
.attr("opacity", 1e-6);
tickEnter.append("svg:line")
@ -172,13 +139,13 @@ d3.chart.bullet = function() {
// Transition the entering ticks to the new scale, x1.
tickEnter.transition()
.duration(duration)
.attr("transform", translate(x1))
.attr("transform", d3_chart_bulletTranslate(x1))
.attr("opacity", 1);
// Transition the updating ticks to the new scale, x1.
var tickUpdate = tick.transition()
.duration(duration)
.attr("transform", translate(x1))
.attr("transform", d3_chart_bulletTranslate(x1))
.attr("opacity", 1);
tickUpdate.select("line")
@ -191,13 +158,13 @@ d3.chart.bullet = function() {
// Transition the exiting ticks to the new scale, x1.
tick.exit().transition()
.duration(duration)
.attr("transform", translate(x1))
.attr("transform", d3_chart_bulletTranslate(x1))
.attr("opacity", 1e-6)
.remove();
// Lastly, restore the original data and update the previous scale!
g.map(d3_chart_bulletData);
x0.domain([0, max]).range(xRange);
x0 = x1;
}
// left, right, top, bottom
@ -227,8 +194,7 @@ d3.chart.bullet = function() {
bullet.width = function(x) {
if (!arguments.length) return width;
x0.range([0, width = x]);
x1.range([0, width]);
width = x;
return bullet;
};
@ -253,14 +219,6 @@ d3.chart.bullet = function() {
return bullet;
};
function d3_chart_bulletTitle(d) {
return d.title;
}
function d3_chart_bulletSubtitle(d) {
return d.subtitle;
}
function d3_chart_bulletRanges(d) {
return d.ranges;
}
@ -276,3 +234,16 @@ function d3_chart_bulletMeasures(d) {
function d3_chart_bulletData(d) {
return d.data;
}
function d3_chart_bulletTranslate(x) {
return function(d) {
return "translate(" + x(d) + ",0)";
};
}
function d3_chart_bulletWidth(x) {
var x0 = x(0);
return function(d) {
return Math.abs(x(d) - x0);
};
}