Skip to content

Commit 5cad4ff

Browse files
committed
lasso and selectbox skeleton
1 parent e536a91 commit 5cad4ff

File tree

7 files changed

+153
-9
lines changed

7 files changed

+153
-9
lines changed

src/components/modebar/buttons.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,24 @@ modeBarButtons.pan2d = {
121121
click: handleCartesian
122122
};
123123

124+
modeBarButtons.select2d = {
125+
name: 'select2d',
126+
title: 'Box Select',
127+
attr: 'dragmode',
128+
val: 'select',
129+
icon: Icons.question, // TODO
130+
click: handleCartesian
131+
};
132+
133+
modeBarButtons.lasso2d = {
134+
name: 'lasso2d',
135+
title: 'Lasso Select',
136+
attr: 'dragmode',
137+
val: 'lasso',
138+
icon: Icons.question, // TODO
139+
click: handleCartesian
140+
};
141+
124142
modeBarButtons.zoomIn2d = {
125143
name: 'zoomIn2d',
126144
title: 'Zoom in',
@@ -179,6 +197,13 @@ modeBarButtons.hoverCompareCartesian = {
179197
click: handleCartesian
180198
};
181199

200+
var DRAGCURSORS = {
201+
pan: 'move',
202+
zoom: 'crosshair',
203+
select: 'crosshair',
204+
lasso: 'crosshair' // TODO: better cursors for select and lasso?
205+
};
206+
182207
function handleCartesian(gd, ev) {
183208
var button = ev.currentTarget,
184209
astr = button.getAttribute('data-attr'),
@@ -230,7 +255,7 @@ function handleCartesian(gd, ev) {
230255
if(fullLayout._hasCartesian) {
231256
Plotly.Fx.setCursor(
232257
fullLayout._paper.select('.nsewdrag'),
233-
{pan:'move', zoom:'crosshair'}[val]
258+
DRAGCURSORS[val]
234259
);
235260
}
236261
Plotly.Fx.supplyLayoutDefaults(gd.layout, fullLayout, gd._fullData);

src/components/modebar/manage.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ function getButtonGroups(fullLayout, buttonsToRemove, buttonsToAdd) {
102102
allAxesFixed = areAllAxesFixed(fullLayout);
103103

104104
if((hasCartesian || hasGL2D) && !allAxesFixed) {
105-
addGroup(['zoom2d', 'pan2d']);
105+
addGroup(['zoom2d', 'pan2d', 'select2d', 'lasso2d']);
106106
addGroup(['zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetScale2d']);
107107
}
108108

src/css/_drag.scss

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
.select-outline {
2+
fill: none;
3+
stroke-width: 1;
4+
shape-rendering: crispEdges;
5+
}
6+
.select-outline-1 {
7+
stroke: white;
8+
}
9+
.select-outline-2 {
10+
stroke: black;
11+
stroke-dasharray: 2px 2px;
12+
}

src/css/style.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66
@import "cursor.scss";
77
@import "modebar.scss";
88
@import "tooltip.scss";
9+
@import "drag.scss";
910
}
1011
@import "notifier.scss";

src/plots/cartesian/graph_interact.js

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@ var d3 = require('d3');
1414
var tinycolor = require('tinycolor2');
1515
var isNumeric = require('fast-isnumeric');
1616
var Events = require('../../lib/events');
17+
var prepSelect = require('./select');
1718

1819
var fx = module.exports = {};
1920

2021
fx.layoutAttributes = {
2122
dragmode: {
2223
valType: 'enumerated',
2324
role: 'info',
24-
values: ['zoom', 'pan', 'orbit', 'turntable'],
25+
values: ['zoom', 'pan', 'select', 'lasso', 'orbit', 'turntable'],
2526
description: 'Determines the mode of drag interactions.'
2627
},
2728
hovermode: {
@@ -1370,16 +1371,39 @@ function dragBox(gd, plotinfo, x, y, w, h, ns, ew) {
13701371

13711372
var dragOptions = {
13721373
element: dragger,
1374+
gd: gd,
1375+
plotinfo: plotinfo,
1376+
xaxes: xa,
1377+
yaxes: ya,
1378+
doubleclick: doubleClick,
13731379
prepFn: function(e, startX, startY) {
1374-
if(ns+ew==='nsew' && ((fullLayout.dragmode==='zoom') ?
1375-
!e.shiftKey : e.shiftKey)) {
1380+
var dragModeNow = gd._fullLayout.dragmode;
1381+
if(ns + ew === 'nsew') {
1382+
// main dragger handles all drag modes, and changes
1383+
// to pan (or to zoom if it already is pan) on shift
1384+
if(e.shiftKey) {
1385+
if(dragModeNow === 'pan') dragModeNow = 'zoom';
1386+
else dragModeNow = 'pan';
1387+
}
1388+
}
1389+
// all other draggers just pan
1390+
else dragModeNow = 'pan';
1391+
1392+
if(dragModeNow === 'lasso') dragOptions.minDrag = 1;
1393+
else dragOptions.minDrag = undefined;
1394+
1395+
if(dragModeNow === 'zoom') {
13761396
dragOptions.moveFn = zoomMove;
13771397
dragOptions.doneFn = zoomDone;
13781398
zoomPrep(e, startX, startY);
1379-
} else {
1399+
}
1400+
else if(dragModeNow === 'pan') {
13801401
dragOptions.moveFn = plotDrag;
13811402
dragOptions.doneFn = dragDone;
13821403
}
1404+
else if(dragModeNow === 'select' || dragModeNow === 'lasso') {
1405+
prepSelect(e, startX, startY, dragOptions, dragModeNow);
1406+
}
13831407
}
13841408
};
13851409

@@ -2003,9 +2027,11 @@ fx.dragElement = function(options) {
20032027

20042028
function onMove(e) {
20052029
var dx = e.clientX - startX,
2006-
dy = e.clientY - startY;
2007-
if(Math.abs(dx)<fx.MINDRAG) dx = 0;
2008-
if(Math.abs(dy)<fx.MINDRAG) dy = 0;
2030+
dy = e.clientY - startY,
2031+
minDrag = options.minDrag || fx.MINDRAG;
2032+
2033+
if(Math.abs(dx) < minDrag) dx = 0;
2034+
if(Math.abs(dy) < minDrag) dy = 0;
20092035
if(dx||dy) gd._dragged = true;
20102036

20112037
if(options.moveFn) options.moveFn(dx, dy, gd._dragged);

src/plots/cartesian/lasso.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* Copyright 2012-2015, Plotly, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
10+
'use strict';
11+
12+
module.exports = function prepLasso(e, startX, startY, dragOptions) {
13+
console.log('lasso start', e, startX, startY, dragOptions);
14+
15+
dragOptions.moveFn = function(dx0, dy0) {
16+
console.log('lasso move', dx0, dy0);
17+
};
18+
19+
dragOptions.doneFn = function(dragged, numclicks) {
20+
console.log('lasso done', dragged, numclicks);
21+
};
22+
};

src/plots/cartesian/select.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* Copyright 2012-2015, Plotly, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
10+
'use strict';
11+
12+
module.exports = function prepSelect(e, startX, startY, dragOptions, mode) {
13+
console.log('select start', e, startX, startY, dragOptions, mode);
14+
var plot = dragOptions.plotinfo.plot,
15+
dragBBox = dragOptions.element.getBoundingClientRect(),
16+
x0 = startX - dragBBox.left,
17+
y0 = startY - dragBBox.top,
18+
x1 = x0,
19+
y1 = y0,
20+
path0 = 'M' + x0 + ',' + y0,
21+
pw = dragOptions.xaxes[0]._length,
22+
ph = dragOptions.yaxes[0]._length,
23+
pts = [[x0, y0]],
24+
outlines = plot.selectAll('path.select-outline').data([1,2]);
25+
26+
// TODO initial dimming of selectable points
27+
28+
outlines.enter()
29+
.append('path')
30+
.attr('class', function(d) { return 'select-outline select-outline-' + d; })
31+
.attr('d', path0 + 'Z');
32+
33+
dragOptions.moveFn = function(dx0, dy0) {
34+
console.log('select move', dx0, dy0);
35+
x1 = Math.max(0, Math.min(pw, dx0 + x0));
36+
y1 = Math.max(0, Math.min(ph, dy0 + y0));
37+
38+
if(mode === 'select') {
39+
outlines.attr('d', path0 + 'H' + x1 + 'V' + y1 + 'H' + x0 + 'Z');
40+
}
41+
else {
42+
pts.push([x1, y1]); // TODO: filter this down to something reasonable
43+
outlines.attr('d', 'M' + pts.join('L'));
44+
}
45+
46+
// TODO - actual selection and dimming!
47+
};
48+
49+
dragOptions.doneFn = function(dragged, numclicks) {
50+
console.log('select done', dragged, numclicks);
51+
if(!dragged && numclicks === 2) dragOptions.doubleclick();
52+
else {
53+
// TODO - select event
54+
}
55+
outlines.remove();
56+
// TODO - remove dimming
57+
};
58+
};

0 commit comments

Comments
 (0)