A Pen by Shelby Sturgis on CodePen.
Created
November 14, 2015 08:30
-
-
Save stormpython/f0af6d10fad5885d3689 to your computer and use it in GitHub Desktop.
Bullet Chart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="bullet"> | |
<svg width=600 height=500></svg> | |
</div> | |
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.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