Skip to content

Instantly share code, notes, and snippets.

@jorpic
Created January 13, 2015 08:01
Show Gist options
  • Save jorpic/31467028ce4b93e53278 to your computer and use it in GitHub Desktop.
Save jorpic/31467028ce4b93e53278 to your computer and use it in GitHub Desktop.
d3.js brush alignment
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body { text-align: center; }
svg { font: 10px sans-serif; }
path, line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.brush .extent {
stroke: #000;
fill-opacity: .125;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://coffeescript.org/extras/coffee-script.js"></script>
<script type="text/coffeescript">
[width, height] = [930, 300]
svg = d3.select('body')
.append('svg')
.attr('width', width).attr('height', height + 30)
.append('g')
x = d3.scale.ordinal()
.domain(d3.time.years(new Date(2002,0,1), new Date(2015,0,1)))
.rangeRoundBands([0, width], .1, .5)
svg.append('g')
.attr('class', 'x axis')
.attr('transform', "translate(0,#{height})")
.call(d3.svg.axis()
.scale(x).tickFormat(d3.time.format '%Y'))
y = d3.scale.linear()
.domain([0,1])
.rangeRound([height, 0])
###
## Draw bars
###
data = x.domain().map (d) -> {date: d, val: Math.random()}
bars = svg.selectAll('.bars').data(data)
.enter().append('rect')
.attr('transform', (d) -> "translate(#{x(d.date)},0)")
.attr('width', x.rangeBand())
.attr('y', (d) -> y d.val)
.attr('height', (d) -> y(0) - y(d.val))
.style('fill', 'teal')
.style('opacity', 0.6)
###
## ## Select date range on the diagram
###
invertScaleL = (scale, val) ->
dom = scale.domain()
res = scale dom[0]
for v in dom
if val <= res
break
res = scale v
res
invertScaleR = (scale, val) ->
w = scale.rangeBand()
dom = scale.domain().slice().reverse()
res = scale(dom[0]) + w
for v in dom
if val >= res
break
res = scale(v) + w
res
brush = d3.svg.brush()
.x(x)
.on('brushend', ->
if d3.event.sourceEvent
# align brushed region to ticks
[a0,b0] = brush.extent()
a1 = invertScaleL(x, a0)
b1 = invertScaleR(x, a1 + b0 - a0)
d3.select(@).transition()
.call(brush.extent [a1, b1])
.call(brush.event))
svg.append('g')
.attr('class', 'brush')
.call(brush)
.selectAll('rect')
.attr('height', height)
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment