Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 41b0fd2

Browse files
authored
Merge pull request #6243 from plotly/selections
Persistent selections for cartesian subplots
2 parents ee85231 + 46709ab commit 41b0fd2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+3414
-1078
lines changed

draftlogs/add_6243.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- add `selections`, `newselection` and `activeselection` options to have
2+
persistent and editable selections over cartesian subplots [[#6243](https://github.com/plotly/plotly.js/pull/6243)]

package-lock.json

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
"mouse-wheel": "^1.2.0",
106106
"native-promise-only": "^0.8.1",
107107
"parse-svg-path": "^0.1.2",
108+
"point-in-polygon": "^1.1.0",
108109
"polybooljs": "^1.2.0",
109110
"probe-image-size": "^7.2.3",
110111
"regl": "npm:@plotly/regl@^2.1.2",
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
'use strict';
2+
3+
var annAttrs = require('../annotations/attributes');
4+
var scatterLineAttrs = require('../../traces/scatter/attributes').line;
5+
var dash = require('../drawing/attributes').dash;
6+
var extendFlat = require('../../lib/extend').extendFlat;
7+
var overrideAll = require('../../plot_api/edit_types').overrideAll;
8+
var templatedArray = require('../../plot_api/plot_template').templatedArray;
9+
var axisPlaceableObjs = require('../../constants/axis_placeable_objects');
10+
11+
module.exports = overrideAll(templatedArray('selection', {
12+
type: {
13+
valType: 'enumerated',
14+
values: ['rect', 'path'],
15+
description: [
16+
'Specifies the selection type to be drawn.',
17+
18+
'If *rect*, a rectangle is drawn linking',
19+
'(`x0`,`y0`), (`x1`,`y0`), (`x1`,`y1`) and (`x0`,`y1`).',
20+
21+
'If *path*, draw a custom SVG path using `path`.'
22+
].join(' ')
23+
},
24+
25+
xref: extendFlat({}, annAttrs.xref, {
26+
description: [
27+
'Sets the selection\'s x coordinate axis.',
28+
axisPlaceableObjs.axisRefDescription('x', 'left', 'right')
29+
].join(' ')
30+
}),
31+
32+
yref: extendFlat({}, annAttrs.yref, {
33+
description: [
34+
'Sets the selection\'s x coordinate axis.',
35+
axisPlaceableObjs.axisRefDescription('y', 'bottom', 'top')
36+
].join(' ')
37+
}),
38+
39+
x0: {
40+
valType: 'any',
41+
description: 'Sets the selection\'s starting x position.'
42+
},
43+
x1: {
44+
valType: 'any',
45+
description: 'Sets the selection\'s end x position.'
46+
},
47+
48+
y0: {
49+
valType: 'any',
50+
description: 'Sets the selection\'s starting y position.'
51+
},
52+
y1: {
53+
valType: 'any',
54+
description: 'Sets the selection\'s end y position.'
55+
},
56+
57+
path: {
58+
valType: 'string',
59+
editType: 'arraydraw',
60+
description: [
61+
'For `type` *path* - a valid SVG path similar to `shapes.path` in data coordinates.',
62+
'Allowed segments are: M, L and Z.'
63+
].join(' ')
64+
},
65+
66+
opacity: {
67+
valType: 'number',
68+
min: 0,
69+
max: 1,
70+
dflt: 0.7,
71+
editType: 'arraydraw',
72+
description: 'Sets the opacity of the selection.'
73+
},
74+
75+
line: {
76+
color: scatterLineAttrs.color,
77+
width: extendFlat({}, scatterLineAttrs.width, {
78+
min: 1,
79+
dflt: 1
80+
}),
81+
dash: extendFlat({}, dash, {
82+
dflt: 'dot'
83+
})
84+
},
85+
}), 'arraydraw', 'from-root');
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
'use strict';
2+
3+
module.exports = {
4+
// max pixels off straight before a lasso select line counts as bent
5+
BENDPX: 1.5,
6+
7+
// smallest dimension allowed for a select box
8+
MINSELECT: 12,
9+
10+
// throttling limit (ms) for selectPoints calls
11+
SELECTDELAY: 100,
12+
13+
// cache ID suffix for throttle
14+
SELECTID: '-select',
15+
};

src/components/selections/defaults.js

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
'use strict';
2+
3+
var Lib = require('../../lib');
4+
var Axes = require('../../plots/cartesian/axes');
5+
var handleArrayContainerDefaults = require('../../plots/array_container_defaults');
6+
7+
var attributes = require('./attributes');
8+
var helpers = require('../shapes/helpers');
9+
10+
module.exports = function supplyLayoutDefaults(layoutIn, layoutOut) {
11+
handleArrayContainerDefaults(layoutIn, layoutOut, {
12+
name: 'selections',
13+
handleItemDefaults: handleSelectionDefaults
14+
});
15+
16+
// Drop rect selections with undefined x0, y0, x1, x1 values.
17+
// In future we may accept partially defined rects e.g.
18+
// a case with only x0 and x1 may be used to define
19+
// [-Infinity, +Infinity] range on the y axis, etc.
20+
var selections = layoutOut.selections;
21+
for(var i = 0; i < selections.length; i++) {
22+
var selection = selections[i];
23+
if(!selection) continue;
24+
if(selection.path === undefined) {
25+
if(
26+
selection.x0 === undefined ||
27+
selection.x1 === undefined ||
28+
selection.y0 === undefined ||
29+
selection.y1 === undefined
30+
) {
31+
layoutOut.selections[i] = null;
32+
}
33+
}
34+
}
35+
};
36+
37+
function handleSelectionDefaults(selectionIn, selectionOut, fullLayout) {
38+
function coerce(attr, dflt) {
39+
return Lib.coerce(selectionIn, selectionOut, attributes, attr, dflt);
40+
}
41+
42+
var path = coerce('path');
43+
var dfltType = path ? 'path' : 'rect';
44+
var selectionType = coerce('type', dfltType);
45+
var noPath = selectionType !== 'path';
46+
if(noPath) delete selectionOut.path;
47+
48+
coerce('opacity');
49+
coerce('line.color');
50+
coerce('line.width');
51+
coerce('line.dash');
52+
53+
// positioning
54+
var axLetters = ['x', 'y'];
55+
for(var i = 0; i < 2; i++) {
56+
var axLetter = axLetters[i];
57+
var gdMock = {_fullLayout: fullLayout};
58+
var ax;
59+
var pos2r;
60+
var r2pos;
61+
62+
// xref, yref
63+
var axRef = Axes.coerceRef(selectionIn, selectionOut, gdMock, axLetter);
64+
65+
// axRefType is 'range' for selections
66+
ax = Axes.getFromId(gdMock, axRef);
67+
ax._selectionIndices.push(selectionOut._index);
68+
r2pos = helpers.rangeToShapePosition(ax);
69+
pos2r = helpers.shapePositionToRange(ax);
70+
71+
// Coerce x0, x1, y0, y1
72+
if(noPath) {
73+
// hack until V3.0 when log has regular range behavior - make it look like other
74+
// ranges to send to coerce, then put it back after
75+
// this is all to give reasonable default position behavior on log axes, which is
76+
// a pretty unimportant edge case so we could just ignore this.
77+
var attr0 = axLetter + '0';
78+
var attr1 = axLetter + '1';
79+
var in0 = selectionIn[attr0];
80+
var in1 = selectionIn[attr1];
81+
selectionIn[attr0] = pos2r(selectionIn[attr0], true);
82+
selectionIn[attr1] = pos2r(selectionIn[attr1], true);
83+
84+
Axes.coercePosition(selectionOut, gdMock, coerce, axRef, attr0);
85+
Axes.coercePosition(selectionOut, gdMock, coerce, axRef, attr1);
86+
87+
var p0 = selectionOut[attr0];
88+
var p1 = selectionOut[attr1];
89+
90+
if(p0 !== undefined && p1 !== undefined) {
91+
// hack part 2
92+
selectionOut[attr0] = r2pos(p0);
93+
selectionOut[attr1] = r2pos(p1);
94+
selectionIn[attr0] = in0;
95+
selectionIn[attr1] = in1;
96+
}
97+
}
98+
}
99+
100+
if(noPath) {
101+
Lib.noneOrAll(selectionIn, selectionOut, ['x0', 'x1', 'y0', 'y1']);
102+
}
103+
}

0 commit comments

Comments
 (0)