|
// general size parameters for the vis |
|
var width = window.innerWidth; |
|
var height = window.innerHeight; |
|
var padding = { top: 40, right: 40, bottom: 40, left: 40 }; |
|
var plotAreaWidth = width - padding.left - padding.right; |
|
var plotAreaHeight = height - padding.top - padding.bottom; |
|
|
|
// when a lasso is completed, filter to the points within the lasso polygon |
|
function handleLassoEnd(lassoPolygon) { |
|
var selectedPoints = points.filter(function (d) { |
|
// note we have to undo any transforms done to the x and y to match with the |
|
// coordinate system in the svg. |
|
var x = d.x + padding.left; |
|
var y = d.y + padding.top; |
|
|
|
return d3.polygonContains(lassoPolygon, [x, y]); |
|
}); |
|
|
|
updateSelectedPoints(selectedPoints); |
|
} |
|
|
|
// reset selected points when starting a new polygon |
|
function handleLassoStart(lassoPolygon) { |
|
updateSelectedPoints([]); |
|
} |
|
|
|
// when we have selected points, update the colors and redraw |
|
function updateSelectedPoints(selectedPoints) { |
|
// if no selected points, reset to all tomato |
|
if (!selectedPoints.length) { |
|
// reset all |
|
points.forEach(function (d) { |
|
d.color = 'tomato'; |
|
}); |
|
|
|
// otherwise gray out selected and color selected black |
|
} else { |
|
points.forEach(function (d) { |
|
d.color = '#eee'; |
|
}); |
|
selectedPoints.forEach(function (d) { |
|
d.color = '#000'; |
|
}); |
|
} |
|
|
|
// redraw with new colors |
|
drawPoints(); |
|
} |
|
|
|
// helper to actually draw points on the canvas |
|
function drawPoints() { |
|
var context = canvas.node().getContext('2d'); |
|
context.save(); |
|
context.clearRect(0, 0, width, height); |
|
context.translate(padding.left, padding.top); |
|
|
|
// draw each point as a rectangle |
|
for (var i = 0; i < points.length; ++i) { |
|
var point = points[i]; |
|
|
|
// draw circles |
|
context.fillStyle = point.color; |
|
context.beginPath(); |
|
context.arc(point.x, point.y, point.r, 0, 2 * Math.PI); |
|
context.fill(); |
|
} |
|
|
|
context.restore(); |
|
} |
|
|
|
// create a container with position relative to handle our canvas layer |
|
// and our SVG interaction layer |
|
var visRoot = d3 |
|
.select(document.body) |
|
.append('div') |
|
.attr('class', 'vis-root') |
|
.style('position', 'relative'); |
|
|
|
// main canvas to draw on |
|
var screenScale = window.devicePixelRatio || 1; |
|
var canvas = visRoot |
|
.append('canvas') |
|
.attr('width', width * screenScale) |
|
.attr('height', height * screenScale) |
|
.style('width', (width + "px")) |
|
.style('height', (height + "px")); |
|
canvas |
|
.node() |
|
.getContext('2d') |
|
.scale(screenScale, screenScale); |
|
|
|
// add in an interaction layer as an SVG |
|
var interactionSvg = visRoot |
|
.append('svg') |
|
.attr('width', width) |
|
.attr('height', height) |
|
.style('position', 'absolute') |
|
.style('top', 0) |
|
.style('left', 0); |
|
|
|
// attach lasso to interaction SVG |
|
var lassoInstance = lasso() |
|
.on('end', handleLassoEnd) |
|
.on('start', handleLassoStart); |
|
|
|
interactionSvg.call(lassoInstance); |
|
|
|
// make up fake data |
|
var points = d3.range(500).map(function () { return ({ |
|
x: Math.random() * plotAreaWidth, |
|
y: Math.random() * plotAreaHeight, |
|
r: Math.random() * 5 + 2, |
|
color: 'tomato', |
|
}); }); |
|
|
|
// initial draw of points |
|
drawPoints(); |
|
|
Yea the dist files are just transpiled to work in older browsers.