constructor(context, options) { // create a clipped SVG Path super(context, options); const { registerViewportChanged, removeViewportChanged, setDomainsCallback, } = context; const uid = slugid.nice(); this.uid = uid; this.options = options; this.removeViewportChanged = removeViewportChanged; this.setDomainsCallback = setDomainsCallback; this.viewportXDomain = null; this.viewportYDomain = null; this.brush = brush(true) .on('brush', this.brushed.bind(this)); this.gBrush = this.gMain .append('g') .attr('id', `brush-${this.uid}`) .call(this.brush); // turn off the ability to select new regions for this brush this.gBrush.selectAll('.overlay') .style('pointer-events', 'none'); // turn off the ability to modify the aspect ratio of the brush this.gBrush.selectAll('.handle--ne') .style('pointer-events', 'none'); this.gBrush.selectAll('.handle--nw') .style('pointer-events', 'none'); this.gBrush.selectAll('.handle--sw') .style('pointer-events', 'none'); this.gBrush.selectAll('.handle--se') .style('pointer-events', 'none'); this.gBrush.selectAll('.handle--n') .style('pointer-events', 'none'); this.gBrush.selectAll('.handle--s') .style('pointer-events', 'none'); registerViewportChanged(uid, this.viewportChanged.bind(this)); // the viewport will call this.viewportChanged immediately upon // hearing registerViewportChanged this.draw(); }
setupSelectionBrush () { const map = this.map const selection = this.brushSel const selectableSelection = map.sel.selectAll('#nodes,#text-labels') const sizeAndLocation = map.canvas.sizeAndLocation() const width = sizeAndLocation.width const height = sizeAndLocation.height const x = sizeAndLocation.x const y = sizeAndLocation.y const turnOffCrosshair = this.turnOffCrosshair.bind(this) // Clear existing brush selection.selectAll('*').remove() // Set a flag so we know that the brush is being cleared at the end of a // successful brush let clearingFlag = false var brush = d3Brush() .extent([ [ x, y ], [ x + width, y + height ] ]) .on('start', () => { this.turnOffCrosshair(selection) // unhide secondary metabolites if they are hidden if (map.settings.get('hide_secondary_metabolites')) { map.settings.set('hide_secondary_metabolites', false) map.draw_everything() map.set_status('Showing secondary metabolites. You can hide them ' + 'again in Settings.', 2000) } }) .on('brush', function () { const shiftKeyOn = event.sourceEvent.shiftKey const rect = d3BrushSelection(this) // Check for no selection (e.g. after clearing brush) if (rect !== null) { // When shift is pressed, ignore the currently selected nodes. // Otherwise, brush all nodes. var selection = shiftKeyOn ? selectableSelection.selectAll('.node:not(.selected),.text-label:not(.selected)') : selectableSelection.selectAll('.node,.text-label') selection.classed('selected', d => { const sx = d.x const sy = d.y return (rect[0][0] <= sx && sx < rect[1][0] && rect[0][1] <= sy && sy < rect[1][1]) }) } }) .on('end', function () { turnOffCrosshair(selection) // Clear brush var rect = d3BrushSelection(this) if (rect === null) { if (clearingFlag) { clearingFlag = false } else { // Empty selection, deselect all map.select_none() } } else { // Not empty, then clear the box clearingFlag = true selection.call(brush.move, null) } }) selection // Initialize brush .call(brush) // Turn off the pan grab icons turnOffCrosshair(selection) }