Skip to content

Commit 412bf9d

Browse files
committed
revamp waterfall marker style logic
- use (increasing|decreasing|totals).marker containers - use calcdata[i][j].dir (like ohlc/candlestick) to determine cont - 🔪 arraysToCalcdata, *.marker* attrs are editType:'style' - adapt Bar.plot and Bar textPointStyle for waterfall use - split out reusable Bar.hoverPoints logic for waterfall use - bring some Bar methods back to `master`
1 parent ce0a56a commit 412bf9d

File tree

11 files changed

+146
-172
lines changed

11 files changed

+146
-172
lines changed

src/components/drawing/index.js

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -362,21 +362,8 @@ drawing.pointStyle = function(s, trace, gd) {
362362
});
363363
};
364364

365-
drawing.waterfallStyle = function(d, trace) {
366-
var marker = trace.marker;
367-
if(marker) return marker;
368-
if(!d.isSum) {
369-
if(d.rawS > 0) return trace.increasing;
370-
return trace.decreasing; // Note here by default we return RED for zero and null
371-
}
372-
return trace.totals;
373-
};
374-
375365
drawing.singlePointStyle = function(d, sel, trace, fns, gd) {
376366
var marker = trace.marker;
377-
if(trace.type === 'waterfall') {
378-
marker = this.waterfallStyle(d, trace);
379-
}
380367
var markerLine = marker.line;
381368

382369
sel.style('opacity',
@@ -512,6 +499,7 @@ drawing.makePointStyleFns = function(trace) {
512499
if(trace.selectedpoints) {
513500
Lib.extendFlat(out, drawing.makeSelectedPointStyleFns(trace));
514501
}
502+
515503
return out;
516504
};
517505

src/traces/bar/hover.js

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,21 @@ var Color = require('../../components/color');
1515
var fillHoverText = require('../scatter/fill_hover_text');
1616

1717
function hoverPoints(pointData, xval, yval, hovermode) {
18+
var barPointData = hoverOnBars(pointData, xval, yval, hovermode);
19+
20+
if(barPointData) {
21+
var cd = barPointData.cd;
22+
var trace = cd[0].trace;
23+
var di = cd[barPointData.index];
24+
25+
barPointData.color = getTraceColor(trace, di);
26+
Registry.getComponentMethod('errorbars', 'hoverInfo')(di, trace, barPointData);
27+
28+
return [barPointData];
29+
}
30+
}
31+
32+
function hoverOnBars(pointData, xval, yval, hovermode) {
1833
var cd = pointData.cd;
1934
var trace = cd[0].trace;
2035
var t = cd[0].t;
@@ -133,24 +148,23 @@ function hoverPoints(pointData, xval, yval, hovermode) {
133148
// in case of bars shifted within groups
134149
pointData[posLetter + 'Spike'] = pa.c2p(di.p, true);
135150

136-
pointData.color = getTraceColor(trace, di);
137151
fillHoverText(di, trace, pointData);
138-
Registry.getComponentMethod('errorbars', 'hoverInfo')(di, trace, pointData);
139-
140152
pointData.hovertemplate = trace.hovertemplate;
141-
return [pointData];
153+
154+
return pointData;
142155
}
143156

144157
function getTraceColor(trace, di) {
145-
var mc = (di.mc !== undefined) ? di.mc : trace.marker.color;
146-
var mlc = (di.mlc !== undefined) ? di.mlc : trace.marker.line.color;
147-
var mlw = (di.mlw !== undefined) ? di.mlw : trace.marker.line.width;
158+
var mc = di.mcc || trace.marker.color;
159+
var mlc = di.mlcc || trace.marker.line.color;
160+
var mlw = di.mlw || trace.marker.line.width;
148161

149162
if(Color.opacity(mc)) return mc;
150163
else if(Color.opacity(mlc) && mlw) return mlc;
151164
}
152165

153166
module.exports = {
154167
hoverPoints: hoverPoints,
168+
hoverOnBars: hoverOnBars,
155169
getTraceColor: getTraceColor
156170
};

src/traces/bar/plot.js

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -103,18 +103,29 @@ module.exports = function plot(gd, plotinfo, cdModule, traceLayer) {
103103
}
104104
}
105105

106-
var lw = (di.mlw + 1 ||
107-
(((trace.marker || {}).line) || {}).width + 1 ||
108-
(di.trace ? ((di.trace.marker || {}).line || {}).width : 0) + 1) - 1;
106+
var lw;
107+
var mc;
108+
var prefix;
109+
110+
if(trace.type === 'waterfall') {
111+
var cont = trace[di.dir].marker;
112+
lw = cont.line.width;
113+
mc = cont.color;
114+
prefix = 'waterfall';
115+
} else {
116+
lw = (di.mlw + 1 || trace.marker.line.width + 1 ||
117+
(di.trace ? di.trace.marker.line.width : 0) + 1) - 1;
118+
mc = di.mc || trace.marker.color;
119+
prefix = 'bar';
120+
}
121+
109122
var offset = d3.round((lw / 2) % 1, 2);
110-
var prefix = trace.type === 'waterfall' ? 'waterfall' : 'bar';
111123
var bargap = fullLayout[prefix + 'gap'];
112124
var bargroupgap = fullLayout[prefix + 'groupgap'];
113125

114126
function roundWithLine(v) {
115127
// if there are explicit gaps, don't round,
116128
// it can make the gaps look crappy
117-
118129
return (bargap === 0 && bargroupgap === 0) ?
119130
d3.round(Math.round(v) - offset, 2) : v;
120131
}
@@ -137,7 +148,7 @@ module.exports = function plot(gd, plotinfo, cdModule, traceLayer) {
137148
// no line, expand to a full pixel to make sure we
138149
// can see them
139150

140-
var op = Color.opacity(di.mc || trace.marker.color);
151+
var op = Color.opacity(mc);
141152
var fixpx = (op < 1 || lw > 0.01) ? roundWithLine : expandToVisible;
142153
x0 = fixpx(x0, x1);
143154
x1 = fixpx(x1, x0);
@@ -146,9 +157,9 @@ module.exports = function plot(gd, plotinfo, cdModule, traceLayer) {
146157
}
147158

148159
Lib.ensureSingle(bar, 'path')
149-
.style('vector-effect', 'non-scaling-stroke')
150-
.attr('d', 'M' + x0 + ',' + y0 + 'V' + y1 + 'H' + x1 + 'V' + y0 + 'Z')
151-
.call(Drawing.setClipUrl, plotinfo.layerClipId, gd);
160+
.style('vector-effect', 'non-scaling-stroke')
161+
.attr('d', 'M' + x0 + ',' + y0 + 'V' + y1 + 'H' + x1 + 'V' + y0 + 'Z')
162+
.call(Drawing.setClipUrl, plotinfo.layerClipId, gd);
152163

153164
appendBarText(gd, bar, cd, i, x0, x1, y0, y1);
154165

src/traces/bar/style.js

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88

9-
109
'use strict';
1110

1211
var d3 = require('d3');
@@ -33,14 +32,10 @@ function style(gd, cd) {
3332
// crispEdges to turn off antialiasing so an artificial gap
3433
// isn't introduced.
3534
.each(function(d) {
36-
var trace = d[0].trace;
37-
var prefix = trace.type === 'waterfall' ? 'waterfall' : 'bar';
38-
39-
if((fullLayout.barmode === 'stack' && barcount > 1) || (
40-
fullLayout[prefix + 'gap'] === 0 &&
41-
fullLayout[prefix + 'groupgap'] === 0 &&
42-
!((d[0].trace.marker || {}).line || {}).width)
43-
) {
35+
if((fullLayout.barmode === 'stack' && barcount > 1) ||
36+
(fullLayout.bargap === 0 &&
37+
fullLayout.bargroupgap === 0 &&
38+
!d[0].trace.marker.line.width)) {
4439
d3.select(this).attr('shape-rendering', 'crispEdges');
4540
}
4641
});
@@ -55,12 +50,12 @@ function style(gd, cd) {
5550
}
5651

5752
function stylePoints(sel, trace, gd) {
58-
var pts = sel.selectAll('path');
59-
var txs = sel.selectAll('text');
60-
61-
Drawing.pointStyle(pts, trace, gd);
53+
Drawing.pointStyle(sel.selectAll('path'), trace, gd);
54+
styleTextPoints(sel, trace, gd);
55+
}
6256

63-
txs.each(function(d) {
57+
function styleTextPoints(sel, trace, gd) {
58+
sel.selectAll('text').each(function(d) {
6459
var tx = d3.select(this);
6560
var font = determineFont(tx, d, trace, gd);
6661
Drawing.font(tx, font);
@@ -164,11 +159,15 @@ function getFontValue(attributeDefinition, attributeValue, index, defaultValue)
164159
}
165160

166161
function getBarColor(cd, trace) {
162+
if(trace.type === 'waterfall') {
163+
return trace[cd.dir].marker.color;
164+
}
167165
return cd.mc || trace.marker.color;
168166
}
169167

170168
module.exports = {
171169
style: style,
170+
styleTextPoints: styleTextPoints,
172171
styleOnSelect: styleOnSelect,
173172
getInsideTextFont: getInsideTextFont,
174173
getOutsideTextFont: getOutsideTextFont,

src/traces/waterfall/arrays_to_calcdata.js

Lines changed: 0 additions & 46 deletions
This file was deleted.

src/traces/waterfall/attributes.js

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,36 @@
1010

1111
var barAttrs = require('../bar/attributes');
1212
var lineAttrs = require('../scatter/attributes').line;
13+
var extendFlat = require('../../lib/extend').extendFlat;
1314

1415
function directionAttrs() {
1516
return {
16-
editType: 'style',
17-
color: barAttrs.marker.color,
18-
opacity: barAttrs.marker.opacity,
19-
line: {
20-
editType: 'style',
21-
color: barAttrs.marker.line.color,
22-
width: barAttrs.marker.line.width
23-
}
17+
marker: {
18+
color: extendFlat({}, barAttrs.marker.color, {
19+
arrayOk: false,
20+
editType: 'style',
21+
description: ''
22+
}),
23+
line: {
24+
color: extendFlat({}, barAttrs.marker.line.color, {
25+
arrayOk: false,
26+
editType: 'style',
27+
description: ''
28+
}),
29+
width: extendFlat({}, barAttrs.marker.line.width, {
30+
arrayOk: false,
31+
editType: 'style',
32+
description: ''
33+
}),
34+
editType: 'style',
35+
},
36+
editType: 'style'
37+
},
38+
editType: 'style'
2439
};
2540
}
2641

2742
module.exports = {
28-
2943
measure: {
3044
valType: 'data_array',
3145
dflt: [],
@@ -58,35 +72,25 @@ module.exports = {
5872
y0: barAttrs.y0,
5973
dy: barAttrs.dy,
6074

61-
r: barAttrs.r,
62-
t: barAttrs.t,
63-
64-
text: barAttrs.text,
6575
hovertext: barAttrs.hovertext,
6676
hovertemplate: barAttrs.hovertemplate,
6777

78+
text: barAttrs.text,
6879
textposition: barAttrs.textposition,
69-
7080
textfont: barAttrs.textfont,
71-
7281
insidetextfont: barAttrs.insidetextfont,
73-
7482
outsidetextfont: barAttrs.outsidetextfont,
75-
7683
constraintext: barAttrs.constraintext,
7784

7885
cliponaxis: barAttrs.cliponaxis,
79-
8086
orientation: barAttrs.orientation,
8187

8288
offset: barAttrs.offset,
83-
8489
width: barAttrs.width,
8590

86-
marker: directionAttrs(),
87-
totals: directionAttrs(),
8891
increasing: directionAttrs(),
8992
decreasing: directionAttrs(),
93+
totals: directionAttrs(),
9094

9195
connector: {
9296
line: {

src/traces/waterfall/calc.js

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
'use strict';
1010

1111
var Axes = require('../../plots/cartesian/axes');
12-
var arraysToCalcdata = require('./arrays_to_calcdata');
12+
var mergeArray = require('../../lib').mergeArray;
1313
var calcSelection = require('../scatter/calc_selection');
1414

1515
function isAbsolute(a) {
@@ -40,37 +40,44 @@ module.exports = function calc(gd, trace) {
4040
// set position and size (as well as for waterfall total size)
4141
var previousSum = 0;
4242
var newSize;
43-
var i;
4443

45-
for(i = 0; i < serieslen; i++) {
44+
for(var i = 0; i < serieslen; i++) {
4645
var amount = size[i] || 0;
47-
cd[i] = {
46+
47+
var cdi = cd[i] = {
48+
i: i,
4849
p: pos[i],
4950
s: amount,
5051
rawS: amount
5152
};
5253

5354
if(isAbsolute(trace.measure[i])) {
54-
previousSum = cd[i].s;
55+
previousSum = cdi.s;
5556

56-
cd[i].isSum = true;
57-
cd[i].s = previousSum;
57+
cdi.isSum = true;
58+
cdi.dir = 'totals';
59+
cdi.s = previousSum;
5860
} else if(isTotal(trace.measure[i])) {
59-
cd[i].isSum = true;
60-
cd[i].s = previousSum;
61-
} else { // default: relative
62-
cd[i].isSum = false;
63-
newSize = cd[i].s;
64-
cd[i].s = previousSum + newSize;
61+
cdi.isSum = true;
62+
cdi.dir = 'totals';
63+
cdi.s = previousSum;
64+
} else {
65+
// default: relative
66+
cdi.isSum = false;
67+
cdi.dir = cdi.rawS < 0 ? 'decreasing' : 'increasing';
68+
newSize = cdi.s;
69+
cdi.s = previousSum + newSize;
6570
previousSum += newSize;
6671
}
6772

6873
if(trace.ids) {
69-
cd[i].id = String(trace.ids[i]);
74+
cdi.id = String(trace.ids[i]);
7075
}
7176
}
7277

73-
arraysToCalcdata(cd, trace);
78+
79+
mergeArray(trace.text, cd, 'tx');
80+
mergeArray(trace.hovertext, cd, 'htx');
7481
calcSelection(cd, trace);
7582

7683
return cd;

0 commit comments

Comments
 (0)