Skip to content

Commit 9492c99

Browse files
committed
Add a dummy scattersmith trace
This is just a copy of scatterpolar with a changed name.
1 parent 96a7d92 commit 9492c99

File tree

9 files changed

+444
-0
lines changed

9 files changed

+444
-0
lines changed

lib/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Plotly.register([
5050
require('./scatterpolar'),
5151
require('./scatterpolargl'),
5252
require('./barpolar'),
53+
require('./scattersmith'),
5354

5455
// transforms
5556
require('./aggregate'),

lib/scattersmith.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict';
2+
3+
module.exports = require('../src/traces/scattersmith');

src/traces/scattersmith/attributes.js

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
'use strict';
2+
3+
var hovertemplateAttrs = require('../../plots/template_attributes').hovertemplateAttrs;
4+
var texttemplateAttrs = require('../../plots/template_attributes').texttemplateAttrs;
5+
var extendFlat = require('../../lib/extend').extendFlat;
6+
var scatterAttrs = require('../scatter/attributes');
7+
var baseAttrs = require('../../plots/attributes');
8+
var lineAttrs = scatterAttrs.line;
9+
10+
module.exports = {
11+
mode: scatterAttrs.mode,
12+
13+
r: {
14+
valType: 'data_array',
15+
editType: 'calc+clearAxisTypes',
16+
description: 'Sets the radial coordinates'
17+
},
18+
19+
theta: {
20+
valType: 'data_array',
21+
editType: 'calc+clearAxisTypes',
22+
description: 'Sets the angular coordinates'
23+
},
24+
25+
r0: {
26+
valType: 'any',
27+
dflt: 0,
28+
editType: 'calc+clearAxisTypes',
29+
description: [
30+
'Alternate to `r`.',
31+
'Builds a linear space of r coordinates.',
32+
'Use with `dr`',
33+
'where `r0` is the starting coordinate and `dr` the step.'
34+
].join(' ')
35+
},
36+
dr: {
37+
valType: 'number',
38+
dflt: 1,
39+
editType: 'calc',
40+
description: 'Sets the r coordinate step.'
41+
},
42+
43+
theta0: {
44+
valType: 'any',
45+
dflt: 0,
46+
editType: 'calc+clearAxisTypes',
47+
description: [
48+
'Alternate to `theta`.',
49+
'Builds a linear space of theta coordinates.',
50+
'Use with `dtheta`',
51+
'where `theta0` is the starting coordinate and `dtheta` the step.'
52+
].join(' ')
53+
},
54+
dtheta: {
55+
valType: 'number',
56+
editType: 'calc',
57+
description: [
58+
'Sets the theta coordinate step.',
59+
'By default, the `dtheta` step equals the subplot\'s period divided',
60+
'by the length of the `r` coordinates.'
61+
].join(' ')
62+
},
63+
64+
thetaunit: {
65+
valType: 'enumerated',
66+
values: ['radians', 'degrees', 'gradians'],
67+
dflt: 'degrees',
68+
editType: 'calc+clearAxisTypes',
69+
description: [
70+
'Sets the unit of input *theta* values.',
71+
'Has an effect only when on *linear* angular axes.'
72+
].join(' ')
73+
},
74+
75+
text: scatterAttrs.text,
76+
texttemplate: texttemplateAttrs({editType: 'plot'}, {
77+
keys: ['r', 'theta', 'text']
78+
}),
79+
hovertext: scatterAttrs.hovertext,
80+
81+
line: {
82+
color: lineAttrs.color,
83+
width: lineAttrs.width,
84+
dash: lineAttrs.dash,
85+
shape: extendFlat({}, lineAttrs.shape, {
86+
values: ['linear', 'spline']
87+
}),
88+
smoothing: lineAttrs.smoothing,
89+
editType: 'calc'
90+
},
91+
connectgaps: scatterAttrs.connectgaps,
92+
93+
marker: scatterAttrs.marker,
94+
cliponaxis: extendFlat({}, scatterAttrs.cliponaxis, {dflt: false}),
95+
96+
textposition: scatterAttrs.textposition,
97+
textfont: scatterAttrs.textfont,
98+
99+
fill: extendFlat({}, scatterAttrs.fill, {
100+
values: ['none', 'toself', 'tonext'],
101+
dflt: 'none',
102+
description: [
103+
'Sets the area to fill with a solid color.',
104+
'Use with `fillcolor` if not *none*.',
105+
'scatterpolar has a subset of the options available to scatter.',
106+
'*toself* connects the endpoints of the trace (or each segment',
107+
'of the trace if it has gaps) into a closed shape.',
108+
'*tonext* fills the space between two traces if one completely',
109+
'encloses the other (eg consecutive contour lines), and behaves like',
110+
'*toself* if there is no trace before it. *tonext* should not be',
111+
'used if one trace does not enclose the other.'
112+
].join(' ')
113+
}),
114+
fillcolor: scatterAttrs.fillcolor,
115+
116+
// TODO error bars
117+
// https://stackoverflow.com/a/26597487/4068492
118+
// error_x (error_r, error_theta)
119+
// error_y
120+
121+
hoverinfo: extendFlat({}, baseAttrs.hoverinfo, {
122+
flags: ['r', 'theta', 'text', 'name']
123+
}),
124+
hoveron: scatterAttrs.hoveron,
125+
hovertemplate: hovertemplateAttrs(),
126+
127+
selected: scatterAttrs.selected,
128+
unselected: scatterAttrs.unselected
129+
};

src/traces/scattersmith/calc.js

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
'use strict';
2+
3+
var isNumeric = require('fast-isnumeric');
4+
var BADNUM = require('../../constants/numerical').BADNUM;
5+
6+
var Axes = require('../../plots/cartesian/axes');
7+
8+
var calcColorscale = require('../scatter/colorscale_calc');
9+
var arraysToCalcdata = require('../scatter/arrays_to_calcdata');
10+
var calcSelection = require('../scatter/calc_selection');
11+
var calcMarkerSize = require('../scatter/calc').calcMarkerSize;
12+
13+
module.exports = function calc(gd, trace) {
14+
var fullLayout = gd._fullLayout;
15+
var subplotId = trace.subplot;
16+
var radialAxis = fullLayout[subplotId].radialaxis;
17+
var angularAxis = fullLayout[subplotId].angularaxis;
18+
var rArray = radialAxis.makeCalcdata(trace, 'r');
19+
var thetaArray = angularAxis.makeCalcdata(trace, 'theta');
20+
var len = trace._length;
21+
var cd = new Array(len);
22+
23+
for(var i = 0; i < len; i++) {
24+
var r = rArray[i];
25+
var theta = thetaArray[i];
26+
var cdi = cd[i] = {};
27+
28+
if(isNumeric(r) && isNumeric(theta)) {
29+
cdi.r = r;
30+
cdi.theta = theta;
31+
} else {
32+
cdi.r = BADNUM;
33+
}
34+
}
35+
36+
var ppad = calcMarkerSize(trace, len);
37+
trace._extremes.x = Axes.findExtremes(radialAxis, rArray, {ppad: ppad});
38+
39+
calcColorscale(gd, trace);
40+
arraysToCalcdata(cd, trace);
41+
calcSelection(cd, trace);
42+
43+
return cd;
44+
};

src/traces/scattersmith/defaults.js

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
'use strict';
2+
3+
var Lib = require('../../lib');
4+
5+
var subTypes = require('../scatter/subtypes');
6+
var handleMarkerDefaults = require('../scatter/marker_defaults');
7+
var handleLineDefaults = require('../scatter/line_defaults');
8+
var handleLineShapeDefaults = require('../scatter/line_shape_defaults');
9+
var handleTextDefaults = require('../scatter/text_defaults');
10+
var handleFillColorDefaults = require('../scatter/fillcolor_defaults');
11+
var PTS_LINESONLY = require('../scatter/constants').PTS_LINESONLY;
12+
13+
var attributes = require('./attributes');
14+
15+
function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
16+
function coerce(attr, dflt) {
17+
return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
18+
}
19+
20+
var len = handleRThetaDefaults(traceIn, traceOut, layout, coerce);
21+
if(!len) {
22+
traceOut.visible = false;
23+
return;
24+
}
25+
26+
coerce('thetaunit');
27+
coerce('mode', len < PTS_LINESONLY ? 'lines+markers' : 'lines');
28+
coerce('text');
29+
coerce('hovertext');
30+
if(traceOut.hoveron !== 'fills') coerce('hovertemplate');
31+
32+
if(subTypes.hasLines(traceOut)) {
33+
handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce);
34+
handleLineShapeDefaults(traceIn, traceOut, coerce);
35+
coerce('connectgaps');
36+
}
37+
38+
if(subTypes.hasMarkers(traceOut)) {
39+
handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {gradient: true});
40+
}
41+
42+
if(subTypes.hasText(traceOut)) {
43+
coerce('texttemplate');
44+
handleTextDefaults(traceIn, traceOut, layout, coerce);
45+
}
46+
47+
var dfltHoverOn = [];
48+
49+
if(subTypes.hasMarkers(traceOut) || subTypes.hasText(traceOut)) {
50+
coerce('cliponaxis');
51+
coerce('marker.maxdisplayed');
52+
dfltHoverOn.push('points');
53+
}
54+
55+
coerce('fill');
56+
57+
if(traceOut.fill !== 'none') {
58+
handleFillColorDefaults(traceIn, traceOut, defaultColor, coerce);
59+
if(!subTypes.hasLines(traceOut)) handleLineShapeDefaults(traceIn, traceOut, coerce);
60+
}
61+
62+
if(traceOut.fill === 'tonext' || traceOut.fill === 'toself') {
63+
dfltHoverOn.push('fills');
64+
}
65+
coerce('hoveron', dfltHoverOn.join('+') || 'points');
66+
67+
Lib.coerceSelectionMarkerOpacity(traceOut, coerce);
68+
}
69+
70+
function handleRThetaDefaults(traceIn, traceOut, layout, coerce) {
71+
var r = coerce('r');
72+
var theta = coerce('theta');
73+
var len;
74+
75+
if(r) {
76+
if(theta) {
77+
len = Math.min(r.length, theta.length);
78+
} else {
79+
len = r.length;
80+
coerce('theta0');
81+
coerce('dtheta');
82+
}
83+
} else {
84+
if(!theta) return 0;
85+
len = traceOut.theta.length;
86+
coerce('r0');
87+
coerce('dr');
88+
}
89+
90+
traceOut._length = len;
91+
return len;
92+
}
93+
94+
module.exports = {
95+
handleRThetaDefaults: handleRThetaDefaults,
96+
supplyDefaults: supplyDefaults
97+
};
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
'use strict';
2+
3+
var Lib = require('../../lib');
4+
var Axes = require('../../plots/cartesian/axes');
5+
6+
module.exports = function formatLabels(cdi, trace, fullLayout) {
7+
var labels = {};
8+
9+
var subplot = fullLayout[trace.subplot]._subplot;
10+
var radialAxis;
11+
var angularAxis;
12+
13+
// for scatterpolargl texttemplate, _subplot is NOT defined, this takes part during the convert step
14+
// TODO we should consider moving the texttemplate formatting logic to the plot step
15+
if(!subplot) {
16+
subplot = fullLayout[trace.subplot];
17+
radialAxis = subplot.radialaxis;
18+
angularAxis = subplot.angularaxis;
19+
} else {
20+
radialAxis = subplot.radialAxis;
21+
angularAxis = subplot.angularAxis;
22+
}
23+
24+
var rVal = radialAxis.c2l(cdi.r);
25+
labels.rLabel = Axes.tickText(radialAxis, rVal, true).text;
26+
27+
// N.B here the ° sign is part of the formatted value for thetaunit:'degrees'
28+
var thetaVal = angularAxis.thetaunit === 'degrees' ? Lib.rad2deg(cdi.theta) : cdi.theta;
29+
labels.thetaLabel = Axes.tickText(angularAxis, thetaVal, true).text;
30+
31+
return labels;
32+
};

src/traces/scattersmith/hover.js

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
'use strict';
2+
3+
var scatterHover = require('../scatter/hover');
4+
5+
function hoverPoints(pointData, xval, yval, hovermode) {
6+
var scatterPointData = scatterHover(pointData, xval, yval, hovermode);
7+
if(!scatterPointData || scatterPointData[0].index === false) return;
8+
9+
var newPointData = scatterPointData[0];
10+
11+
// hovering on fill case
12+
if(newPointData.index === undefined) {
13+
return scatterPointData;
14+
}
15+
16+
var subplot = pointData.subplot;
17+
var cdi = newPointData.cd[newPointData.index];
18+
var trace = newPointData.trace;
19+
20+
if(!subplot.isPtInside(cdi)) return;
21+
22+
newPointData.xLabelVal = undefined;
23+
newPointData.yLabelVal = undefined;
24+
makeHoverPointText(cdi, trace, subplot, newPointData);
25+
newPointData.hovertemplate = trace.hovertemplate;
26+
return scatterPointData;
27+
}
28+
29+
function makeHoverPointText(cdi, trace, subplot, pointData) {
30+
var radialAxis = subplot.radialAxis;
31+
var angularAxis = subplot.angularAxis;
32+
radialAxis._hovertitle = 'r';
33+
angularAxis._hovertitle = 'θ';
34+
35+
var fullLayout = {};
36+
fullLayout[trace.subplot] = {_subplot: subplot};
37+
var labels = trace._module.formatLabels(cdi, trace, fullLayout);
38+
pointData.rLabel = labels.rLabel;
39+
pointData.thetaLabel = labels.thetaLabel;
40+
41+
var hoverinfo = cdi.hi || trace.hoverinfo;
42+
var text = [];
43+
function textPart(ax, val) {
44+
text.push(ax._hovertitle + ': ' + val);
45+
}
46+
47+
if(!trace.hovertemplate) {
48+
var parts = hoverinfo.split('+');
49+
50+
if(parts.indexOf('all') !== -1) parts = ['r', 'theta', 'text'];
51+
if(parts.indexOf('r') !== -1) textPart(radialAxis, pointData.rLabel);
52+
if(parts.indexOf('theta') !== -1) textPart(angularAxis, pointData.thetaLabel);
53+
54+
if(parts.indexOf('text') !== -1 && pointData.text) {
55+
text.push(pointData.text);
56+
delete pointData.text;
57+
}
58+
59+
pointData.extraText = text.join('<br>');
60+
}
61+
}
62+
63+
module.exports = {
64+
hoverPoints: hoverPoints,
65+
makeHoverPointText: makeHoverPointText
66+
};

0 commit comments

Comments
 (0)