Skip to content

Instantly share code, notes, and snippets.

@stormpython
Created November 14, 2015 08:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stormpython/f0af6d10fad5885d3689 to your computer and use it in GitHub Desktop.
Save stormpython/f0af6d10fad5885d3689 to your computer and use it in GitHub Desktop.
Bullet Chart
<div id="bullet">
<svg width=600 height=500></svg>
</div>
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
var chart = bullet()
.width(600)
.height(75);
d3.select("#bullet").select('svg')
.append('g').attr('transform', 'translate(0, 0)')
.datum({ ranges: [45, 80, 120], measures: [85, 150], markers: [75]})
.call(chart);
function bullet() {
var margin = { top:20, right: 20, bottom: 20, left: 20 };
var width = 500;
var height = 500;
var scale = d3.scale.linear();
var axis = d3.svg.axis().orient('bottom');
var range = {};
var measure = {};
var marker = {};
function chart(g) {
g.each(function (data, index) {
var sort = function (a, b) { return b - a; };
data.ranges = data.ranges.reverse();
data.measures = data.measures.reverse();
data.markers = data.markers.reverse();
var domain = d3.entries(data).map(function (d) {
return d.value;
}).reduce(function (a, b) {
return a.concat(b);
}, []);
width = width - margin.right - margin.left;
height = height - margin.top - margin.bottom;
scale.domain([0, d3.max(domain)])
.range([0, width]);
var measureBarHeight = height / 3;
var halfHeight = height / 2;
var halfMeasureBarHeight = measureBarHeight / 2;
var g = d3.select(this).selectAll('g')
.data([data]);
g.exit().remove();
g.enter().append('g');
g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
g.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + height + ')')
.call(axis.scale(scale).tickSize(6));
var ranges = g.selectAll('rect.range')
.data(data.ranges);
ranges.exit().remove();
ranges.enter().append('rect').attr('class', 'range');
ranges
.attr('x', function () { return scale(0); })
.attr('y', scale(0))
.attr('width', function (d) { return scale(d); })
.attr('height', height)
.attr('fill', range.fill || function (d, i) {
if (i === 0) return '#eee';
if (i === 1) return '#ddd';
return '#ccc';
})
.attr('fill-opacity', range.fillOpacity || 1)
.attr('stroke', range.stroke)
.attr('stroke-width', range.strokeWidth)
.attr('stroke-opacity', range.strokeOpacity);
var measures = g.selectAll('rect.measure')
.data(data.measures);
measures.exit().remove();
measures.enter().append('rect').attr('class', 'measure');
measures
.attr('x', function () { return scale(0); })
.attr('y', halfHeight - halfMeasureBarHeight)
.attr('width', function (d) { return scale(d); })
.attr('height', measureBarHeight)
.attr('fill', measure.fill || function (d, i) {
return i === 0 ? 'lightsteelblue' : 'steelblue';
})
.attr('fill-opacity', measure.fillOpacity || 1)
.attr('stroke', measure.stroke)
.attr('stroke-width', measure.strokeWidth)
.attr('stroke-opacity', measure.strokeOpacity);
var markers = g.selectAll('g.marker')
.data(data.markers);
markers.exit().remove();
markers.enter().append('g').attr('class', 'marker');
markers
.attr('transform', function (d) {
return 'translate(' + scale(d) + ',' + (halfHeight - halfMeasureBarHeight) + ')';
})
.append('path')
.attr('d', function () {
return 'M ' + -halfMeasureBarHeight + ' ' +
-measureBarHeight + ' L 0 0 ' + halfMeasureBarHeight +
' ' + -measureBarHeight + ' Z';
})
.attr('fill', marker.fill || 'black')
.attr('fill-opacity', marker.fillOpacity)
.attr('stroke', marker.stroke || 'none')
.attr('stroke-width', marker.strokeWidth)
.attr('stroke-opacity', marker.strokeOpacity);
});
}
// Public API
chart.margin = function (_) {
if (!arguments.length) return margin;
margin.top = typeof _.top !== 'undefined' ? _.top : margin.top;
margin.right = typeof _.right !== 'undefined' ? _.right : margin.right;
margin.bottom = typeof _.bottom !== 'undefined' ? _.bottom : margin.bottom;
margin.left = typeof _.left !== 'undefined' ? _.left : margin.left;
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.scale = function (_) {
if (!arguments.length) return scale;
scale = _;
return chart;
};
chart.range = function (_) {
if (!arguments.length) return range;
range.fill = typeof _.fill !== 'undefined' ? _.fill : range.fill;
range.fillOpacity = typeof _.fillOpacity !== 'undefined' ? _.fillOpacity : range.fillOpacity;
range.stroke = typeof _.stroke !== 'undefined' ? _.stroke : range.stroke;
range.strokeWidth = typeof _.strokeWidth !== 'undefined' ? _.strokeWidth : range.strokeWidth;
range.strokeOpacity = typeof _.strokeOpacity !== 'undefined' ? _.strokeOpacity : range.strokeOpacity;
return chart;
};
chart.measure = function (_) {
if (!arguments.length) return measure;
measure.fill = typeof _.fill !== 'undefined' ? _.fill : measure.fill;
measure.fillOpacity = typeof _.fillOpacity !== 'undefined' ? _.fillOpacity : measure.fillOpacity;
measure.stroke = typeof _.stroke !== 'undefined' ? _.stroke : measure.stroke;
measure.strokeWidth = typeof _.strokeWidth !== 'undefined' ? _.strokeWidth : measure.strokeWidth;
measure.strokeOpacity = typeof _.strokeOpacity !== 'undefined' ? _.strokeOpacity : measure.strokeOpacity;
return chart;
};
chart.measure = function (_) {
if (!arguments.length) return measure;
marker.fill = typeof _.fill !== 'undefined' ? _.fill : marker.fill;
marker.fillOpacity = typeof _.fillOpacity !== 'undefined' ? _.fillOpacity : marker.fillOpacity;
marker.stroke = typeof _.stroke !== 'undefined' ? _.stroke : marker.stroke;
marker.strokeWidth = typeof _.strokeWidth !== 'undefined' ? _.strokeWidth : marker.strokeWidth;
marker.strokeOpacity = typeof _.strokeOpacity !== 'undefined' ? _.strokeOpacity : marker.strokeOpacity;
return chart;
};
return chart;
}
.axis path {
display: none;
}
.axis line {
fill: none;
stroke: grey;
shape-rendering: crispEdges;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment