|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<style> |
|
.axis path, |
|
.axis line { |
|
fill: none; |
|
stroke: #000; |
|
shape-rendering: crispEdges; |
|
} |
|
|
|
.hidden { |
|
opacity: 0.3; |
|
} |
|
|
|
|
|
.extent { |
|
fill: #000; |
|
fill-opacity: .125; |
|
stroke: #fff; |
|
} |
|
</style> |
|
<body> |
|
<script src="//d3js.org/d3.v3.js"></script> |
|
<script> |
|
|
|
var margin = {top: 20, right: 50, bottom: 30, left: 50}, |
|
width = 960 - margin.left - margin.right, |
|
height = 450 - margin.top - margin.bottom; |
|
|
|
var x = d3.scale.linear() |
|
.range([0, width]) |
|
.domain([0, 10]); |
|
|
|
var y = d3.scale.linear() |
|
.range([height, 0]) |
|
.domain([0, 10]); |
|
|
|
var xAxis = d3.svg.axis() |
|
.scale(x) |
|
.orient("bottom"); |
|
|
|
var yAxis = d3.svg.axis() |
|
.scale(y) |
|
.orient("left"); |
|
|
|
var curPt = d3.select('body') |
|
.append('p') |
|
.html("Current point: ") |
|
.append('span') |
|
.attr('id', 'curPt'); |
|
|
|
var svg = d3.select('body').insert('svg', 'p') |
|
.attr('width', width + margin.left + margin.right) |
|
.attr('height', height + margin.top + margin.bottom) |
|
.append('g') |
|
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); |
|
|
|
svg.append('g') |
|
.attr('class', 'x axis') |
|
.attr('transform', 'translate(0,'+height+')') |
|
.call(xAxis); |
|
|
|
svg.append('g') |
|
.attr('class', 'y axis') |
|
.call(yAxis); |
|
|
|
var brush = d3.svg.brush() |
|
.x(x) |
|
.y(y) |
|
.on("brush", function() { |
|
var e = brush.extent(); |
|
svg.selectAll('circle').classed('hidden', function(d) { |
|
return e[0][0] > d[0] || d[0] > e[1][0] |
|
|| e[0][1] > d[1] || d[1] > e[1][1]; |
|
} |
|
); |
|
}) |
|
.on("brushend", function() { |
|
if (brush.empty()) svg.selectAll('circle').classed('hidden', false); |
|
d3.select('.points').style('pointer-events', null); |
|
dispatched = false; |
|
}); |
|
|
|
var dispatched = false; |
|
svg.append('g').attr('class', 'brush').call(brush); |
|
svg.on('mousedown', function() { |
|
d3.select('.points').style('pointer-events', 'none'); |
|
|
|
|
|
if (!dispatched) { |
|
dispatched = true; |
|
var bubbleEvent = new Event('mousedown'); |
|
bubbleEvent.pageX = d3.event.pageX; |
|
bubbleEvent.clientX = d3.event.clientX; |
|
bubbleEvent.pageY = d3.event.pageY; |
|
bubbleEvent.clientY = d3.event.clientY; |
|
// d3.select('.brush').node().dispatchEvent(bubbleEvent); |
|
|
|
var pos = d3.mouse(this); |
|
var b = d3.select('rect.extent').node().getBBox(); |
|
|
|
// test if outside of bounds of brush extent |
|
if (pos[0] < b.x - 3 || pos[1] < b.y - 3 || |
|
pos[0] > b.x + b.width + 3 || |
|
pos[1] > b.y + b.height + 3) { |
|
|
|
// also do special things for resizing rects, but not necessary in this example |
|
|
|
// bubbleEvent.target = d3.select('rect.background').node(); |
|
d3.select('.brush rect.background').node().dispatchEvent(bubbleEvent); |
|
} |
|
else { |
|
d3.select('.brush rect.extent').node().dispatchEvent(bubbleEvent); |
|
} |
|
} |
|
}, true); |
|
|
|
var data = d3.range(50).map(function() { return [Math.random() * 10, Math.random() * 10]; }); |
|
|
|
svg.append('g') |
|
.attr('class', 'points') |
|
.selectAll('circle') |
|
.data(data).enter() |
|
.append('circle') |
|
.attr('cx', function(d) { return x(d[0]); }) |
|
.attr('cy', function(d) { return y(d[1]); }) |
|
.attr('r', 10) |
|
.style('fill', 'steelblue') |
|
.on('mouseover', function(d) { |
|
curPt.html("[" + d[0] + ", " + d[1] + "]"); |
|
}) |
|
.on('mouseout', function(d) { |
|
curPt.html(""); |
|
}); /* |
|
.on('mousedown', function() { |
|
var bubbleEvent = new Event('mousedown'); |
|
bubbleEvent.pageX = d3.event.pageX; |
|
bubbleEvent.clientX = d3.event.clientX; |
|
bubbleEvent.pageY = d3.event.pageY; |
|
bubbleEvent.clientY = d3.event.clientY; |
|
|
|
// figure out where we are |
|
var pos = d3.mouse(this); |
|
var b = d3.select('rect.extent').node().getBBox(); |
|
|
|
// test if outside of bounds of brush extent |
|
if (pos[0] < b.x - 3 || pos[1] < b.y - 3 || |
|
pos[0] > b.x + b.width + 3 || |
|
pos[1] > b.y + b.height + 3) { |
|
|
|
// also do special things for resizing rects, but not necessary in this example |
|
|
|
// bubbleEvent.target = d3.select('rect.background').node(); |
|
d3.select('rect.background').node().dispatchEvent(bubbleEvent); |
|
} |
|
else { |
|
// bubbleEvent.target = d3.select('rect.extent').node(); |
|
d3.select('rect.extent').node().dispatchEvent(bubbleEvent); |
|
} |
|
});*/ |
|
|
|
</script> |