Skip to content

Implement attributes base, offset and width in bar traces (issue 80) #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 31 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
03e5072
bar: use descriptive variable names
n-riesco Oct 6, 2016
bbdc385
bar: convert closure into function
n-riesco Oct 7, 2016
7b14fcd
bar: refactor code to group bars
n-riesco Oct 7, 2016
fe66e3c
bar: rename `barpositions` to `setOffsetAndWidth`
n-riesco Oct 10, 2016
d422f67
bar: refactor code into function `setBaseAndSize`
n-riesco Oct 10, 2016
97da55b
bar: replace t.dbar with t.bargroupwidth
n-riesco Oct 12, 2016
93ca66e
bar: Move code for `overlay` mode into a function
n-riesco Oct 12, 2016
80fdfbd
bar: refactor code into functions for each barmode
n-riesco Oct 13, 2016
3b87e85
bar: use Sieve to stack bars in setBaseAndSize
n-riesco Oct 14, 2016
a7ca755
bar: add functions stackBars and normalizeBars
n-riesco Oct 14, 2016
1400311
bar: fix image test failure in hist_grouped
n-riesco Oct 17, 2016
4294cad
bar: do not normalise bars with no size
n-riesco Oct 17, 2016
4866cda
bar: Add attributes base, offset and width
n-riesco Oct 19, 2016
79f2e8d
bar: add function sieveBars
n-riesco Oct 19, 2016
10b678b
bar: do not assume initial bar base is zero
n-riesco Oct 19, 2016
23f7415
bar: ensure size axis includes bar bases
n-riesco Oct 20, 2016
6f05b34
bar: do not stack traces that set bar base
n-riesco Oct 20, 2016
d4f7747
bar: implement attributes base, offset and width
n-riesco Oct 21, 2016
0e6e0f1
test: add bar charts using base, offset and width
n-riesco Oct 21, 2016
e83f4c5
bar: guard against invalid base items
n-riesco Oct 21, 2016
f4143e8
bar: guard against invalid offset or width items
n-riesco Oct 21, 2016
125c537
bar: remove use of forEach
n-riesco Oct 21, 2016
f0a0c92
bar: set base, offset and width default to null
n-riesco Oct 21, 2016
2ca7605
bar: add note to setGroupPositionsInOverlayMode
n-riesco Oct 21, 2016
497121d
bar: fix expansion of position axis
n-riesco Oct 24, 2016
54a0967
test: bar pinning tests
n-riesco Oct 24, 2016
6f58cd0
test: update bar base tests
n-riesco Oct 24, 2016
bb93aba
bar: interpret trace data as sizes
n-riesco Oct 24, 2016
307d955
test: update bar_attrs_* mock images
n-riesco Oct 24, 2016
bad5c51
test: update mock bar_attrs_group_norm
n-riesco Oct 24, 2016
6c6d680
test: update bar_attrs_group_norm baseline
n-riesco Oct 24, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions src/traces/bar/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,44 @@ module.exports = {
].join(' ')
},

base: {
valType: 'any',
dflt: null,
arrayOk: true,
role: 'info',
description: [

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make the fact that these attributes are optional, we usually set the dflt: null (e.g. contour trace start, end, size).

Note that, null are ignored upon Lib.nestedProperty(/**/).set(), so your fullTrace.base === undefined will still work.

'Sets where the bar base is drawn (in position axis units).',
'In *stack* or *relative* barmode,',
'traces that set *base* will be excluded',
'and drawn in *overlay* mode instead.'
].join(' ')
},

offset: {
valType: 'number',
dflt: null,
arrayOk: true,
role: 'info',
description: [
'Shifts the position where the bar is drawn',
'(in position axis units).',
'In *group* barmode,',
'traces that set *offset* will be excluded',
'and drawn in *overlay* mode instead.'
].join(' ')
},

width: {
valType: 'number',
dflt: null,
min: 0,
arrayOk: true,
role: 'info',
description: [
'Sets the bar width (in position axis units).'
].join(' ')
},

marker: marker,

r: scatterAttrs.r,
Expand Down
35 changes: 33 additions & 2 deletions src/traces/bar/calc.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ module.exports = function calc(gd, trace) {
var xa = Axes.getFromId(gd, trace.xaxis || 'x'),
ya = Axes.getFromId(gd, trace.yaxis || 'y'),
orientation = trace.orientation || ((trace.x && !trace.y) ? 'h' : 'v'),
pos, size, i;
sa, pos, size, i;

if(orientation === 'h') {
sa = xa;
size = xa.makeCalcdata(trace, 'x');
pos = ya.makeCalcdata(trace, 'y');
}
else {
sa = ya;
size = ya.makeCalcdata(trace, 'y');
pos = xa.makeCalcdata(trace, 'x');
}
Expand All @@ -40,14 +42,43 @@ module.exports = function calc(gd, trace) {
var serieslen = Math.min(pos.length, size.length),
cd = [];

// set position
for(i = 0; i < serieslen; i++) {

// add bars with non-numeric sizes to calcdata
// so that ensure that traces with gaps are
// plotted in the correct order

if(isNumeric(pos[i])) {
cd.push({p: pos[i], s: size[i], b: 0});
cd.push({p: pos[i]});
}
}

// set base
var base = trace.base,
b;

if(Array.isArray(base)) {
for(i = 0; i < Math.min(base.length, cd.length); i++) {
b = sa.d2c(base[i]);
cd[i].b = (isNumeric(b)) ? b : 0;
}
for(; i < cd.length; i++) {
cd[i].b = 0;
}
}
else {
b = sa.d2c(base);
b = (isNumeric(b)) ? b : 0;
for(i = 0; i < cd.length; i++) {
cd[i].b = b;
}
}

// set size
for(i = 0; i < cd.length; i++) {
if(isNumeric(size[i])) {
cd[i].s = size[i];
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/traces/bar/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
}

coerce('orientation', (traceOut.x && !traceOut.y) ? 'h' : 'v');
coerce('base');
coerce('offset');
coerce('width');
coerce('text');

handleStyleDefaults(traceIn, traceOut, coerce, defaultColor, layout);
Expand Down
3 changes: 2 additions & 1 deletion src/traces/bar/hover.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
xa = pointData.xa,
ya = pointData.ya,
barDelta = (hovermode === 'closest') ?
t.barwidth / 2 : t.dbar * (1 - xa._gd._fullLayout.bargap) / 2,
t.barwidth / 2 :
t.bargroupwidth,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice simplification. 👍

barPos;

if(hovermode !== 'closest') barPos = function(di) { return di.p; };
Expand Down
29 changes: 19 additions & 10 deletions src/traces/bar/plot.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,30 +34,39 @@ module.exports = function plot(gd, plotinfo, cdbar) {
.attr('class', 'points')
.each(function(d) {
var t = d[0].t,
trace = d[0].trace;
trace = d[0].trace,
poffset = t.poffset,
poffsetIsArray = Array.isArray(poffset),
barwidth = t.barwidth,
barwidthIsArray = Array.isArray(barwidth);

arraysToCalcdata(d);

d3.select(this).selectAll('path')
.data(Lib.identity)
.enter().append('path')
.each(function(di) {
.each(function(di, i) {
// now display the bar
// clipped xf/yf (2nd arg true): non-positive
// log values go off-screen by plotwidth
// so you see them continue if you drag the plot
var p0 = di.p + ((poffsetIsArray) ? poffset[i] : poffset),
p1 = p0 + ((barwidthIsArray) ? barwidth[i] : barwidth),
s0 = di.b,
s1 = s0 + di.s;

var x0, x1, y0, y1;
if(trace.orientation === 'h') {
y0 = ya.c2p(t.poffset + di.p, true);
y1 = ya.c2p(t.poffset + di.p + t.barwidth, true);
x0 = xa.c2p(di.b, true);
x1 = xa.c2p(di.s + di.b, true);
y0 = ya.c2p(p0, true);
y1 = ya.c2p(p1, true);
x0 = xa.c2p(s0, true);
x1 = xa.c2p(s1, true);
}
else {
x0 = xa.c2p(t.poffset + di.p, true);
x1 = xa.c2p(t.poffset + di.p + t.barwidth, true);
y1 = ya.c2p(di.s + di.b, true);
y0 = ya.c2p(di.b, true);
x0 = xa.c2p(p0, true);
x1 = xa.c2p(p1, true);
y0 = ya.c2p(s0, true);
y1 = ya.c2p(s1, true);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very clean here. 🍻

}

if(!isNumeric(x0) || !isNumeric(x1) ||
Expand Down
Loading