Skip to content

Commit f49828a

Browse files
committed
introducing transitions for bar trace
1 parent b5f0316 commit f49828a

File tree

4 files changed

+64
-9
lines changed

4 files changed

+64
-9
lines changed

Diff for: src/traces/bar/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ module.exports = {
2828
name: 'bar',
2929
basePlotModule: require('../../plots/cartesian'),
3030
categories: ['bar-like', 'cartesian', 'svg', 'bar', 'oriented', 'errorBarsOK', 'showLegend', 'zoomScale'],
31+
animatable: true,
3132
meta: {
3233
description: [
3334
'The data visualized by the span of the bars is set in `y`',

Diff for: src/traces/bar/plot.js

+41-9
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,28 @@ function getXY(di, xa, ya, isHorizontal) {
5151
return isHorizontal ? [s, p] : [p, s];
5252
}
5353

54-
function plot(gd, plotinfo, cdModule, traceLayer, opts) {
54+
function transition(selection, opts, makeOnCompleteCallback) {
55+
if(hasTransition(opts)) {
56+
var onComplete;
57+
if(makeOnCompleteCallback) {
58+
onComplete = makeOnCompleteCallback();
59+
}
60+
return selection
61+
.transition()
62+
.duration(opts.duration)
63+
.ease(opts.easing)
64+
.each('end', function() { onComplete && onComplete(); })
65+
.each('interrupt', function() { onComplete && onComplete(); });
66+
} else {
67+
return selection;
68+
}
69+
}
70+
71+
function hasTransition(transitionOpts) {
72+
return transitionOpts && transitionOpts.duration > 0;
73+
}
74+
75+
function plot(gd, plotinfo, cdModule, traceLayer, opts, makeOnCompleteCallback) {
5576
var xa = plotinfo.xaxis;
5677
var ya = plotinfo.yaxis;
5778
var fullLayout = gd._fullLayout;
@@ -96,7 +117,6 @@ function plot(gd, plotinfo, cdModule, traceLayer, opts) {
96117
// clipped xf/yf (2nd arg true): non-positive
97118
// log values go off-screen by plotwidth
98119
// so you see them continue if you drag the plot
99-
100120
var xy = getXY(di, xa, ya, isHorizontal);
101121

102122
var x0 = xy[0][0];
@@ -118,6 +138,9 @@ function plot(gd, plotinfo, cdModule, traceLayer, opts) {
118138
}
119139
di.isBlank = isBlank;
120140

141+
if(isBlank && isHorizontal) x1 = x0;
142+
if(isBlank && !isHorizontal) y1 = y0;
143+
121144
// in waterfall mode `between` we need to adjust bar end points to match the connector width
122145
if(adjustPixel) {
123146
if(isHorizontal) {
@@ -178,12 +201,19 @@ function plot(gd, plotinfo, cdModule, traceLayer, opts) {
178201
y1 = fixpx(y1, y0);
179202
}
180203

181-
Lib.ensureSingle(bar, 'path')
204+
var sel = transition(Lib.ensureSingle(bar, 'path'), opts, makeOnCompleteCallback);
205+
sel
182206
.style('vector-effect', 'non-scaling-stroke')
183-
.attr('d', isBlank ? 'M0,0Z' : 'M' + x0 + ',' + y0 + 'V' + y1 + 'H' + x1 + 'V' + y0 + 'Z')
207+
.attr('display', function() { return isBlank ? 'none' : null;})
208+
.attr('d', 'M' + x0 + ',' + y0 + 'V' + y1 + 'H' + x1 + 'V' + y0 + 'Z')
184209
.call(Drawing.setClipUrl, plotinfo.layerClipId, gd);
185210

186-
appendBarText(gd, plotinfo, bar, cd, i, x0, x1, y0, y1, opts);
211+
if(hasTransition(opts)) {
212+
var styleFns = Drawing.makePointStyleFns(trace);
213+
Drawing.singlePointStyle(di, sel, trace, styleFns, gd);
214+
}
215+
216+
appendBarText(gd, plotinfo, bar, cd, i, x0, x1, y0, y1, opts, makeOnCompleteCallback);
187217

188218
if(plotinfo.layerClipId) {
189219
Drawing.hideOutsideRangePoint(di, bar.select('text'), xa, ya, trace.xcalendar, trace.ycalendar);
@@ -197,10 +227,10 @@ function plot(gd, plotinfo, cdModule, traceLayer, opts) {
197227
});
198228

199229
// error bars are on the top
200-
Registry.getComponentMethod('errorbars', 'plot')(gd, bartraces, plotinfo);
230+
Registry.getComponentMethod('errorbars', 'plot')(gd, bartraces, plotinfo, opts);
201231
}
202232

203-
function appendBarText(gd, plotinfo, bar, calcTrace, i, x0, x1, y0, y1, opts) {
233+
function appendBarText(gd, plotinfo, bar, calcTrace, i, x0, x1, y0, y1, opts, makeOnCompleteCallback) {
204234
var xa = plotinfo.xaxis;
205235
var ya = plotinfo.yaxis;
206236

@@ -212,7 +242,6 @@ function appendBarText(gd, plotinfo, bar, calcTrace, i, x0, x1, y0, y1, opts) {
212242
.text(text)
213243
.attr({
214244
'class': 'bartext bartext-' + textPosition,
215-
transform: '',
216245
'text-anchor': 'middle',
217246
// prohibit tex interpretation until we can handle
218247
// tex and regular text together
@@ -325,9 +354,12 @@ function appendBarText(gd, plotinfo, bar, calcTrace, i, x0, x1, y0, y1, opts) {
325354
(textPosition === 'outside') ?
326355
outsideTextFont : insideTextFont);
327356

357+
var currentTransform = textSelection.attr('transform');
358+
textSelection.attr('transform', '');
328359
textBB = Drawing.bBox(textSelection.node()),
329360
textWidth = textBB.width,
330361
textHeight = textBB.height;
362+
textSelection.attr('transform', currentTransform);
331363

332364
if(textWidth <= 0 || textHeight <= 0) {
333365
textSelection.remove();
@@ -360,7 +392,7 @@ function appendBarText(gd, plotinfo, bar, calcTrace, i, x0, x1, y0, y1, opts) {
360392
}));
361393
}
362394

363-
textSelection.attr('transform', transform);
395+
transition(textSelection, opts, makeOnCompleteCallback).attr('transform', transform);
364396
}
365397

366398
function getRotateFromAngle(angle) {

Diff for: test/image/baselines/animation_bar.png

8.9 KB
Loading

Diff for: test/image/mocks/animation_bar.json

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"data": [{
3+
"type": "bar",
4+
"x": ["A", "B", "C"],
5+
"y": [24, 5, 8],
6+
"error_y": {"array": [3, 2, 1]}
7+
}],
8+
"layout": {
9+
"width": 400,
10+
"height": 400,
11+
"yaxis": {"range": [0, 30]}
12+
},
13+
"frames": [
14+
{"data": [{"y": [12, 15, 10]}]},
15+
{"data": [{"error_y": {"array": [5, 4, 1]}}]},
16+
{"data": [{"marker": {"color": ["red", "blue", "green"]}}]},
17+
{"data": [{"width": 0.25}]},
18+
{"data": [{"marker": {"line": {"width": 10}}}]},
19+
{"data": [{"marker": {"line": {"color": ["orange", "yellow", "blue"]}}}]},
20+
{"layout": {"yaxis": {"range": [0, 20]}}}
21+
]
22+
}

0 commit comments

Comments
 (0)