Skip to content

Commit 524716e

Browse files
committed
Add preventEvent to select() and deselect(). Refactor lasso props.
1 parent 064e7e4 commit 524716e

4 files changed

Lines changed: 165 additions & 37 deletions

File tree

README.md

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ Regl-scatterplot supports two color modes: coloring by value or coloring by cate
6464
```javascript
6565
scatterplot.draw([
6666
// x, y, category, value
67-
0.2, -0.1, 0, 0.1337,
68-
0.3, 0.1, 0, 0.3371,
69-
-0.9, 0.8, 1, 0.3713,
67+
[0.2, -0.1, 0, 0.1337],
68+
[0.3, 0.1, 0, 0.3371],
69+
[-0.9, 0.8, 1, 0.3713],
7070
]);
7171
```
7272

@@ -281,14 +281,38 @@ scatterplot.set({
281281
scatterplot.set({ showRecticle: true, recticleColor: [1, 0, 0, 0.66] });
282282
```
283283

284-
<a name="scatterplot.select" href="#scatterplot.select">#</a> scatterplot.<b>select</b>()
284+
<a name="scatterplot.select" href="#scatterplot.select">#</a> scatterplot.<b>select</b>(<i>points</i>, <i>options = {}</i>)
285285

286-
Select some points, such that they get visually highlighted. This will trigger
287-
a `select` event.
286+
Select some points, such that they get visually highlighted. This will trigger a `select` event unless `options.preventEvent === true`.
288287

289-
<a name="scatterplot.deselect" href="#scatterplot.deselect">#</a> scatterplot.<b>deselect</b>()
288+
**Arguments:**
290289

291-
Deselect all selected points. This will trigger a `deselect` event.
290+
- `points` is an array of point indices.
291+
- `options` [optional] is an object with the following properties:
292+
- `preventEvent`: if `true` the `select` will not be published.
293+
294+
**Examples:**
295+
296+
```javascript
297+
// Let's say we have three points
298+
scatterplot.draw([
299+
[0.1, 0.1],
300+
[0.2, 0.2],
301+
[0.3, 0.3],
302+
]);
303+
304+
// To select the first and second point we have to do
305+
scatterplot.select([0, 1]);
306+
```
307+
308+
<a name="scatterplot.deselect" href="#scatterplot.deselect">#</a> scatterplot.<b>deselect</b>(<i>options = {}</i>)
309+
310+
Deselect all selected points. This will trigger a `deselect` event unless `options.preventEvent === true`.
311+
312+
**Arguments:**
313+
314+
- `options` [optional] is an object with the following properties:
315+
- `preventEvent`: if `true` the `deselect` will not be published.
292316

293317
<a name="scatterplot.destroy" href="#scatterplot.destroy">#</a> scatterplot.<b>destroy</b>()
294318

src/constants.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ export const COLOR_NORMAL_IDX = 0;
55
export const COLOR_NUM_STATES = 4;
66
export const FLOAT_BYTES = Float32Array.BYTES_PER_ELEMENT;
77
export const GL_EXTENSIONS = ['OES_standard_derivatives', 'OES_texture_float'];
8-
export const LASSO_MIN_DELAY = 10;
9-
export const LASSO_MIN_DIST = 3;
8+
9+
// Default lasso
10+
export const DEFAULT_LASSO_MIN_DELAY = 10;
11+
export const DEFAULT_LASSO_MIN_DIST = 3;
1012

1113
// Default attribute
1214
export const DEFAULT_DATA_ASPECT_RATIO = 1;

src/index.js

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import {
2727
DEFAULT_DISTANCE,
2828
DEFAULT_HEIGHT,
2929
DEFAULT_LASSO_COLOR,
30+
DEFAULT_LASSO_MIN_DELAY,
31+
DEFAULT_LASSO_MIN_DIST,
3032
DEFAULT_SHOW_RECTICLE,
3133
DEFAULT_RECTICLE_COLOR,
3234
DEFAULT_POINT_OUTLINE_WIDTH,
@@ -37,8 +39,6 @@ import {
3739
DEFAULT_VIEW,
3840
DEFAULT_WIDTH,
3941
FLOAT_BYTES,
40-
LASSO_MIN_DELAY,
41-
LASSO_MIN_DIST,
4242
} from './constants';
4343

4444
import {
@@ -94,8 +94,8 @@ const createScatterplot = (initialProperties = {}) => {
9494
canvas: initialCanvas = document.createElement('canvas'),
9595
colorBy: initialColorBy = DEFAULT_COLOR_BY,
9696
lassoColor: initialLassoColor = DEFAULT_LASSO_COLOR,
97-
lassoMinDelay: initialLassoMinDelay = LASSO_MIN_DELAY,
98-
lassoMinDist: initialLassoMinDist = LASSO_MIN_DIST,
97+
lassoMinDelay: initialLassoMinDelay = DEFAULT_LASSO_MIN_DELAY,
98+
lassoMinDist: initialLassoMinDist = DEFAULT_LASSO_MIN_DIST,
9999
showRecticle: initialShowRecticle = DEFAULT_SHOW_RECTICLE,
100100
recticleColor: initialRecticleColor = DEFAULT_RECTICLE_COLOR,
101101
pointColor: initialPointColor = DEFAULT_COLOR_NORMAL,
@@ -296,15 +296,15 @@ const createScatterplot = (initialProperties = {}) => {
296296
return pointsInPolygon;
297297
};
298298

299-
const deselect = () => {
299+
const deselect = ({ preventEvent = false } = {}) => {
300300
if (selection.length) {
301-
pubSub.publish('deselect');
301+
if (!preventEvent) pubSub.publish('deselect');
302302
selection = [];
303303
drawRaf(); // eslint-disable-line no-use-before-define
304304
}
305305
};
306306

307-
const select = (points) => {
307+
const select = (points, { preventEvent = false } = {}) => {
308308
selection = points;
309309

310310
selectedPointsIndexBuffer({
@@ -313,9 +313,7 @@ const createScatterplot = (initialProperties = {}) => {
313313
data: new Float32Array(selection),
314314
});
315315

316-
pubSub.publish('select', {
317-
points: selection,
318-
});
316+
if (!preventEvent) pubSub.publish('select', { points: selection });
319317

320318
drawRaf(); // eslint-disable-line no-use-before-define
321319
};
@@ -329,7 +327,16 @@ const createScatterplot = (initialProperties = {}) => {
329327
return [...mousePosition];
330328
};
331329

330+
const lassoStart = () => {
331+
// Fix camera for the lasso selection
332+
camera.config({ isFixed: true });
333+
// Make sure we start a new lasso selection
334+
lassoPrevMousePos = undefined;
335+
lasso.clear();
336+
};
337+
332338
const lassoEnd = () => {
339+
camera.config({ isFixed: false });
333340
// const t0 = performance.now();
334341
const pointsInLasso = findPointsInLasso(lassoScatterPos);
335342
// console.log(`found ${pointsInLasso.length} in ${performance.now() - t0} msec`);
@@ -349,12 +356,7 @@ const createScatterplot = (initialProperties = {}) => {
349356
mouseDownPosition = getRelativeMousePosition(event);
350357
mouseDownShift = event.shiftKey;
351358

352-
if (mouseDownShift) {
353-
// Fix camera for the lasso selection
354-
camera.config({ isFixed: true });
355-
// Make sure we start a new lasso selection
356-
lassoPrevMousePos = undefined;
357-
}
359+
if (mouseDownShift) lassoStart();
358360
};
359361

360362
const mouseUpHandler = () => {
@@ -364,7 +366,6 @@ const createScatterplot = (initialProperties = {}) => {
364366

365367
if (mouseDownShift) {
366368
mouseDownShift = false;
367-
camera.config({ isFixed: false });
368369
lassoEnd();
369370
}
370371
};
@@ -375,7 +376,7 @@ const createScatterplot = (initialProperties = {}) => {
375376
const currentMousePosition = getRelativeMousePosition(event);
376377
const clickDist = dist(...currentMousePosition, ...mouseDownPosition);
377378

378-
if (clickDist >= LASSO_MIN_DIST) return;
379+
if (clickDist >= lassoMinDist) return;
379380

380381
const clostestPoint = raycast();
381382
if (clostestPoint >= 0) select([clostestPoint]);
@@ -972,6 +973,8 @@ const createScatterplot = (initialProperties = {}) => {
972973
if (property === 'colorBy') return colorBy;
973974
if (property === 'height') return height;
974975
if (property === 'lassoColor') return lassoColor;
976+
if (property === 'lassoMinDelay') return lassoMinDelay;
977+
if (property === 'lassoMinDist') return lassoMinDist;
975978
if (property === 'opacity') return opacity;
976979
if (property === 'pointColor')
977980
return pointColors.length === 1 ? pointColors[0] : pointColors;

tests/index.js

Lines changed: 108 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ import {
2020
DEFAULT_POINT_SIZE,
2121
DEFAULT_POINT_SIZE_SELECTED,
2222
DEFAULT_WIDTH,
23-
LASSO_MIN_DELAY,
24-
LASSO_MIN_DIST,
23+
DEFAULT_LASSO_MIN_DELAY,
24+
DEFAULT_LASSO_MIN_DIST,
2525
} from '../src/constants';
2626

2727
import {
@@ -502,33 +502,69 @@ test('set({ opacity })', async (t) => {
502502
);
503503
});
504504

505-
test('set({ lassoColor })', async (t) => {
505+
test('set({ lassoColor, lassoMinDist, lassoMinDelay })', async (t) => {
506506
const scatterplot = createScatterplot({ canvas: createCanvas() });
507507

508-
// Check default lasso color
508+
// Check default lasso color, min distance, and min delay
509509
t.equal(
510510
scatterplot.get('lassoColor'),
511511
DEFAULT_LASSO_COLOR,
512512
`lassoColor should be set to ${DEFAULT_LASSO_COLOR}`
513513
);
514+
t.equal(
515+
scatterplot.get('lassoMinDist'),
516+
DEFAULT_LASSO_MIN_DIST,
517+
`lassoMinDist should be set to ${DEFAULT_LASSO_MIN_DIST}`
518+
);
519+
t.equal(
520+
scatterplot.get('lassoMinDelay'),
521+
DEFAULT_LASSO_MIN_DELAY,
522+
`lassoMinDelay should be set to ${DEFAULT_LASSO_MIN_DELAY}`
523+
);
514524

515525
const lassoColor = [1, 0, 0, 1];
526+
const lassoMinDist = 10;
527+
const lassoMinDelay = 150;
516528

517-
scatterplot.set({ lassoColor });
529+
scatterplot.set({ lassoColor, lassoMinDist, lassoMinDelay });
518530

519531
t.equal(
520532
scatterplot.get('lassoColor'),
521533
lassoColor,
522534
`lassoColor should be set to ${lassoColor}`
523535
);
536+
t.equal(
537+
scatterplot.get('lassoMinDist'),
538+
lassoMinDist,
539+
`lassoMinDist should be set to ${lassoMinDist}`
540+
);
541+
t.equal(
542+
scatterplot.get('lassoMinDelay'),
543+
lassoMinDelay,
544+
`lassoMinDelay should be set to ${lassoMinDelay}`
545+
);
524546

525-
scatterplot.set({ lassoColor: null });
547+
scatterplot.set({
548+
lassoColor: null,
549+
lassoMinDist: null,
550+
lassoMinDelay: null,
551+
});
526552

527553
t.equal(
528554
scatterplot.get('lassoColor'),
529555
lassoColor,
530556
'lassoColor should not be nullifyable'
531557
);
558+
t.equal(
559+
scatterplot.get('lassoMinDist'),
560+
lassoMinDist,
561+
'lassoMinDist should not be nullifyable'
562+
);
563+
t.equal(
564+
scatterplot.get('lassoMinDelay'),
565+
lassoMinDelay,
566+
'lassoMinDelay should not be nullifyable'
567+
);
532568
});
533569

534570
test('set({ pointOutlineWidth })', async (t) => {
@@ -696,10 +732,10 @@ test('draw(), clear(), publish("select")', async (t) => {
696732
t.equal(selectedPoints.length, 0, 'should have deselected one point');
697733

698734
// Test that mousedown + mousemove + click is not interpreted as a click when
699-
// the cursor moved more than `LASSO_MIN_DIST` in between mousedown and
735+
// the cursor moved more than `DEFAULT_LASSO_MIN_DIST` in between mousedown and
700736
// mouseup
701737
canvas.dispatchEvent(
702-
createMouseEvent('mousedown', hdim - LASSO_MIN_DIST, hdim)
738+
createMouseEvent('mousedown', hdim - DEFAULT_LASSO_MIN_DIST, hdim)
703739
);
704740
canvas.dispatchEvent(createMouseEvent('click', hdim, hdim));
705741

@@ -763,7 +799,7 @@ test('lasso selection with publish("select")', async (t) => {
763799

764800
await asyncForEach(mousePositions, async (mousePosition) => {
765801
window.dispatchEvent(createMouseEvent('mousemove', ...mousePosition));
766-
await wait(LASSO_MIN_DELAY + 5);
802+
await wait(DEFAULT_LASSO_MIN_DELAY + 5);
767803
});
768804

769805
window.dispatchEvent(createMouseEvent('mouseup'));
@@ -846,3 +882,66 @@ test('point hover with publish("pointover") and publish("pointout")', async (t)
846882
// 'should have published the translated view'
847883
// );
848884
// });
885+
886+
/* ----------------------------- Other Methods ------------------------------ */
887+
888+
test('select()', async (t) => {
889+
const scatterplot = createScatterplot({ canvas: createCanvas() });
890+
891+
const points = [
892+
[0, 0],
893+
[1, 1],
894+
[1, -1],
895+
[-1, -1],
896+
[-1, 1],
897+
];
898+
scatterplot.draw(points);
899+
900+
// TODO: fix this!
901+
await wait(250);
902+
903+
let selectedPoints = [];
904+
const selectHandler = ({ points: newSelectedPoints }) => {
905+
selectedPoints = [...newSelectedPoints];
906+
};
907+
const deselectHandler = () => {
908+
selectedPoints = [];
909+
};
910+
scatterplot.subscribe('select', selectHandler);
911+
scatterplot.subscribe('deselect', deselectHandler);
912+
913+
scatterplot.select([0, 2, 4]);
914+
915+
await wait(0);
916+
917+
t.ok(
918+
flatArrayEqual([0, 2, 4], selectedPoints),
919+
'should have selected point 0, 2, and 4'
920+
);
921+
922+
scatterplot.deselect();
923+
924+
await wait(0);
925+
926+
t.equal(selectedPoints.length, 0, 'should have deselected all points');
927+
928+
scatterplot.select([0, 2, 4], { preventEvent: true });
929+
930+
await wait(0);
931+
932+
t.equal(
933+
selectedPoints.length,
934+
0,
935+
'should have silently selected three points'
936+
);
937+
938+
scatterplot.select([0, 2, 4]);
939+
scatterplot.deselect({ preventEvent: true });
940+
941+
await wait(0);
942+
943+
t.ok(
944+
flatArrayEqual([0, 2, 4], selectedPoints),
945+
'should have silently deselected points'
946+
);
947+
});

0 commit comments

Comments
 (0)