Skip to content

Commit cad13aa

Browse files
committed
add funnel - new trace files
1 parent 8846193 commit cad13aa

File tree

11 files changed

+785
-0
lines changed

11 files changed

+785
-0
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Copyright 2012-2019, 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+
'use strict';
10+
11+
var mergeArray = require('../../lib').mergeArray;
12+
13+
// arrayOk attributes, merge them into calcdata array
14+
module.exports = function arraysToCalcdata(cd, trace) {
15+
for(var i = 0; i < cd.length; i++) cd[i].i = i;
16+
17+
mergeArray(trace.text, cd, 'tx');
18+
mergeArray(trace.hovertext, cd, 'htx');
19+
20+
var marker = trace.marker;
21+
if(marker) {
22+
mergeArray(marker.opacity, cd, 'mo');
23+
mergeArray(marker.color, cd, 'mc');
24+
25+
var markerLine = marker.line;
26+
if(markerLine) {
27+
mergeArray(markerLine.color, cd, 'mlc');
28+
mergeArray(markerLine.width, cd, 'mlw');
29+
}
30+
}
31+
};

src/traces/funnel/attributes.js

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/**
2+
* Copyright 2012-2019, 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+
'use strict';
10+
11+
var pieAtts = require('../pie/attributes');
12+
var barAttrs = require('../bar/attributes');
13+
var lineAttrs = require('../scatter/attributes').line;
14+
var extendFlat = require('../../lib/extend').extendFlat;
15+
var Color = require('../../components/color');
16+
17+
module.exports = {
18+
x: barAttrs.x,
19+
x0: barAttrs.x0,
20+
dx: barAttrs.dx,
21+
y: barAttrs.y,
22+
y0: barAttrs.y0,
23+
dy: barAttrs.dy,
24+
25+
hovertext: barAttrs.hovertext,
26+
hovertemplate: barAttrs.hovertemplate,
27+
28+
textinfo: extendFlat({}, pieAtts.textinfo, {
29+
editType: 'plot',
30+
flags: ['label', 'text', 'percent of initial', 'percent of previous', 'percent of total', 'value'],
31+
description: [
32+
'Determines which trace information appear on the graph.'
33+
].join(' ')
34+
}),
35+
36+
text: barAttrs.text,
37+
textposition: extendFlat({}, barAttrs.textposition, {dflt: 'auto'}),
38+
insidetextcenter: {
39+
valType: 'boolean',
40+
dflt: false,
41+
role: 'info',
42+
editType: 'plot',
43+
description: [
44+
'Determines if texts are kept at center in `textposition` *inside* mode.'
45+
].join(' ')
46+
},
47+
textfont: barAttrs.textfont,
48+
insidetextfont: barAttrs.insidetextfont,
49+
outsidetextfont: barAttrs.outsidetextfont,
50+
constraintext: barAttrs.constraintext,
51+
52+
cliponaxis: barAttrs.cliponaxis,
53+
orientation: barAttrs.orientation,
54+
55+
offset: barAttrs.offset,
56+
width: barAttrs.width,
57+
58+
marker: barAttrs.marker,
59+
60+
connector: {
61+
fillcolor: {
62+
valType: 'color',
63+
role: 'style',
64+
editType: 'plot', // TODO: could we set this to 'style' ?
65+
description: [
66+
'Sets the fill color.'
67+
].join(' ')
68+
},
69+
line: {
70+
color: extendFlat({}, lineAttrs.color, {dflt: Color.defaultLine}),
71+
width: extendFlat({}, lineAttrs.width, {
72+
dflt: 0,
73+
editType: 'plot', // TODO: could we set this to 'style' ?
74+
}),
75+
dash: lineAttrs.dash,
76+
editType: 'plot' // TODO: could we set this to 'style' ?
77+
},
78+
visible: {
79+
valType: 'boolean',
80+
dflt: true,
81+
role: 'info',
82+
editType: 'plot',
83+
description: [
84+
'Determines if connector regions and lines are drawn.'
85+
].join(' ')
86+
},
87+
editType: 'plot'
88+
},
89+
90+
offsetgroup: barAttrs.offsetgroup,
91+
alignmentgroup: barAttrs.offsetgroup
92+
};

src/traces/funnel/calc.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/**
2+
* Copyright 2012-2019, 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+
'use strict';
10+
11+
var Axes = require('../../plots/cartesian/axes');
12+
var arraysToCalcdata = require('./arrays_to_calcdata');
13+
var calcSelection = require('../scatter/calc_selection');
14+
var BADNUM = require('../../constants/numerical').BADNUM;
15+
16+
module.exports = function calc(gd, trace) {
17+
var xa = Axes.getFromId(gd, trace.xaxis || 'x');
18+
var ya = Axes.getFromId(gd, trace.yaxis || 'y');
19+
var size, pos, i, cdi;
20+
21+
if(trace.orientation === 'h') {
22+
size = xa.makeCalcdata(trace, 'x');
23+
pos = ya.makeCalcdata(trace, 'y');
24+
} else {
25+
size = ya.makeCalcdata(trace, 'y');
26+
pos = xa.makeCalcdata(trace, 'x');
27+
}
28+
29+
// create the "calculated data" to plot
30+
var serieslen = Math.min(pos.length, size.length);
31+
var cd = new Array(serieslen);
32+
33+
trace._base = [];
34+
35+
// set position and size
36+
for(i = 0; i < serieslen; i++) {
37+
// treat negative values as bad numbers
38+
if(size[i] < 0) size[i] = BADNUM;
39+
40+
var connectToNext = false;
41+
if(size[i] !== BADNUM) {
42+
if(i + 1 < serieslen && size[i + 1] !== BADNUM) {
43+
connectToNext = true;
44+
}
45+
}
46+
47+
cdi = cd[i] = {
48+
p: pos[i],
49+
s: size[i],
50+
cNext: connectToNext
51+
};
52+
53+
trace._base[i] = -0.5 * size[i];
54+
55+
if(trace.ids) {
56+
cdi.id = String(trace.ids[i]);
57+
}
58+
59+
// calculate total values
60+
if(i === 0) cd[0].vTotal = 0;
61+
cd[0].vTotal += fixNum(cdi.s);
62+
63+
// ratio from initial value
64+
cdi.begR = fixNum(cdi.s) / fixNum(cd[0].s);
65+
}
66+
67+
var prevGoodNum;
68+
for(i = 0; i < serieslen; i++) {
69+
cdi = cd[i];
70+
if(cdi.s === BADNUM) continue;
71+
72+
// ratio of total value
73+
cdi.sumR = cdi.s / cd[0].vTotal;
74+
75+
// ratio of previous (good) value
76+
cdi.difR = (prevGoodNum !== undefined) ? cdi.s / prevGoodNum : 1;
77+
78+
prevGoodNum = cdi.s;
79+
}
80+
81+
arraysToCalcdata(cd, trace);
82+
calcSelection(cd, trace);
83+
84+
return cd;
85+
};
86+
87+
function fixNum(a) {
88+
return (a === BADNUM) ? 0 : a;
89+
}

src/traces/funnel/cross_trace_calc.js

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/**
2+
* Copyright 2012-2019, 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+
'use strict';
10+
11+
var setGroupPositions = require('../bar/cross_trace_calc').setGroupPositions;
12+
13+
module.exports = function crossTraceCalc(gd, plotinfo) {
14+
var fullLayout = gd._fullLayout;
15+
var fullData = gd._fullData;
16+
var calcdata = gd.calcdata;
17+
var xa = plotinfo.xaxis;
18+
var ya = plotinfo.yaxis;
19+
var includeOtherTypes = false;
20+
var funnels = [];
21+
var funnelsVert = [];
22+
var funnelsHorz = [];
23+
var cd, i;
24+
25+
var mayHideX = false;
26+
var mayHideY = false;
27+
28+
for(i = 0; i < fullData.length; i++) {
29+
var fullTrace = fullData[i];
30+
var isHorizontal = (fullTrace.orientation === 'h');
31+
32+
if(
33+
fullTrace.visible === true &&
34+
fullTrace.xaxis === xa._id &&
35+
fullTrace.yaxis === ya._id
36+
) {
37+
if(fullTrace.type === 'funnel') {
38+
cd = calcdata[i];
39+
40+
if(isHorizontal) {
41+
funnelsHorz.push(cd);
42+
mayHideX = true;
43+
} else {
44+
funnelsVert.push(cd);
45+
mayHideY = true;
46+
}
47+
48+
funnels.push(cd);
49+
} else { // TODO: figure out which trace types should be exluded here?
50+
includeOtherTypes = true;
51+
}
52+
}
53+
}
54+
55+
if(!includeOtherTypes) {
56+
if(mayHideX) xa._hide = true;
57+
if(mayHideY) ya._hide = true;
58+
}
59+
60+
// funnel version of 'barmode', 'barnorm', 'bargap' and 'bargroupgap'
61+
var mockGd = {
62+
_fullLayout: {
63+
_axisMatchGroups: fullLayout._axisMatchGroups,
64+
_alignmentOpts: fullLayout._alignmentOpts,
65+
barmode: fullLayout.funnelmode,
66+
barnorm: fullLayout.funnelnorm,
67+
bargap: fullLayout.funnelgap,
68+
bargroupgap: fullLayout.funnelgroupgap
69+
}
70+
};
71+
72+
setGroupPositions(mockGd, xa, ya, funnelsVert);
73+
setGroupPositions(mockGd, ya, xa, funnelsHorz);
74+
75+
for(i = 0; i < funnels.length; i++) {
76+
cd = funnels[i];
77+
78+
for(var j = 0; j < cd.length; j++) {
79+
if(j + 1 < cd.length) {
80+
cd[j].nextP0 = cd[j + 1].p0;
81+
cd[j].nextS0 = cd[j + 1].s0;
82+
83+
cd[j].nextP1 = cd[j + 1].p1;
84+
cd[j].nextS1 = cd[j + 1].s1;
85+
}
86+
}
87+
}
88+
};

src/traces/funnel/defaults.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/**
2+
* Copyright 2012-2019, 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+
'use strict';
10+
11+
var Lib = require('../../lib');
12+
13+
var handleGroupingDefaults = require('../bar/defaults').handleGroupingDefaults;
14+
var handleText = require('../bar/defaults').handleText;
15+
var handleXYDefaults = require('../scatter/xy_defaults');
16+
var attributes = require('./attributes');
17+
var Color = require('../../components/color');
18+
19+
function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
20+
function coerce(attr, dflt) {
21+
return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
22+
}
23+
24+
var len = handleXYDefaults(traceIn, traceOut, layout, coerce);
25+
if(!len) {
26+
traceOut.visible = false;
27+
return;
28+
}
29+
30+
coerce('orientation', (traceOut.x && !traceOut.y) ? 'h' : 'v');
31+
coerce('offset');
32+
coerce('width');
33+
34+
coerce('text');
35+
coerce('textinfo');
36+
37+
coerce('hovertext');
38+
coerce('hovertemplate');
39+
40+
handleText(traceIn, traceOut, layout, coerce, false);
41+
42+
coerce('marker.color', defaultColor);
43+
coerce('marker.line.color', Color.defaultLine);
44+
coerce('marker.line.width');
45+
46+
var connectorVisible = coerce('connector.visible');
47+
if(connectorVisible) {
48+
coerce('connector.fillcolor', Color.addOpacity(defaultColor, 0.5));
49+
50+
var connectorLineWidth = coerce('connector.line.width');
51+
if(connectorLineWidth) {
52+
coerce('connector.line.color');
53+
coerce('connector.line.dash');
54+
}
55+
}
56+
}
57+
58+
function crossTraceDefaults(fullData, fullLayout) {
59+
var traceIn, traceOut;
60+
61+
function coerce(attr) {
62+
return Lib.coerce(traceOut._input, traceOut, attributes, attr);
63+
}
64+
65+
if(fullLayout.funnelmode === 'group') {
66+
for(var i = 0; i < fullData.length; i++) {
67+
traceOut = fullData[i];
68+
traceIn = traceOut._input;
69+
70+
handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce);
71+
}
72+
}
73+
}
74+
75+
module.exports = {
76+
supplyDefaults: supplyDefaults,
77+
crossTraceDefaults: crossTraceDefaults,
78+
handleGroupingDefaults: handleGroupingDefaults
79+
};

0 commit comments

Comments
 (0)