Skip to content

Commit f56e071

Browse files
authored
Merge pull request #1315 from plotly/fix-annotation-animation
Still animate layout objects if there's no transitioned axis
2 parents 5da3791 + ed83238 commit f56e071

File tree

2 files changed

+101
-6
lines changed

2 files changed

+101
-6
lines changed

src/plots/cartesian/transition_axes.js

+21-6
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,23 @@ module.exports = function transitionAxes(gd, newLayout, transitionOpts, makeOnCo
100100
var updatedAxisIds = Object.keys(updates);
101101
var affectedSubplots = computeAffectedSubplots(fullLayout, updatedAxisIds, updates);
102102

103+
function updateLayoutObjs() {
104+
function redrawObjs(objArray, method, shortCircuit) {
105+
for(var i = 0; i < objArray.length; i++) {
106+
method(gd, i);
107+
108+
// once is enough for images (which doesn't use the `i` arg anyway)
109+
if(shortCircuit) return;
110+
}
111+
}
112+
113+
redrawObjs(fullLayout.annotations || [], Registry.getComponentMethod('annotations', 'drawOne'));
114+
redrawObjs(fullLayout.shapes || [], Registry.getComponentMethod('shapes', 'drawOne'));
115+
redrawObjs(fullLayout.images || [], Registry.getComponentMethod('images', 'draw'), true);
116+
}
117+
103118
if(!affectedSubplots.length) {
119+
updateLayoutObjs();
104120
return false;
105121
}
106122

@@ -114,23 +130,23 @@ module.exports = function transitionAxes(gd, newLayout, transitionOpts, makeOnCo
114130
Axes.doTicks(gd, activeAxIds[i], true);
115131
}
116132

117-
function redrawObjs(objArray, method) {
133+
function redrawObjs(objArray, method, shortCircuit) {
118134
for(i = 0; i < objArray.length; i++) {
119135
var obji = objArray[i];
120136

121137
if((activeAxIds.indexOf(obji.xref) !== -1) ||
122138
(activeAxIds.indexOf(obji.yref) !== -1)) {
123139
method(gd, i);
124140
}
141+
142+
// once is enough for images (which doesn't use the `i` arg anyway)
143+
if(shortCircuit) return;
125144
}
126145
}
127146

128-
// annotations and shapes 'draw' method is slow,
129-
// use the finer-grained 'drawOne' method instead
130-
131147
redrawObjs(fullLayout.annotations || [], Registry.getComponentMethod('annotations', 'drawOne'));
132148
redrawObjs(fullLayout.shapes || [], Registry.getComponentMethod('shapes', 'drawOne'));
133-
redrawObjs(fullLayout.images || [], Registry.getComponentMethod('images', 'draw'));
149+
redrawObjs(fullLayout.images || [], Registry.getComponentMethod('images', 'draw'), true);
134150
}
135151

136152
function unsetSubplotTransform(subplot) {
@@ -202,7 +218,6 @@ module.exports = function transitionAxes(gd, newLayout, transitionOpts, makeOnCo
202218

203219
ticksAndAnnotations(subplot.xaxis, subplot.yaxis);
204220

205-
206221
var xa2 = subplot.xaxis;
207222
var ya2 = subplot.yaxis;
208223

test/jasmine/tests/annotations_test.js

+80
Original file line numberDiff line numberDiff line change
@@ -1344,3 +1344,83 @@ describe('annotation effects', function() {
13441344
.then(done);
13451345
});
13461346
});
1347+
1348+
describe('animating annotations', function() {
1349+
var gd;
1350+
1351+
// Two slightly different 1x1 pngs:
1352+
var img1 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQYV2P4z/C/HgAGfgJ+p8YU1AAAAABJRU5ErkJggg==';
1353+
var img2 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQYV2P4//9/PQAJewN9w0ic/wAAAABJRU5ErkJggg==';
1354+
1355+
beforeEach(function() {
1356+
gd = createGraphDiv();
1357+
});
1358+
1359+
afterEach(destroyGraphDiv);
1360+
1361+
it('updates annoations when no axis update present', function(done) {
1362+
1363+
function assertAnnotations(expected) {
1364+
var texts = Plotly.d3.select(gd).selectAll('.annotation .annotation-text');
1365+
expect(expected.length).toEqual(texts.size());
1366+
1367+
texts.each(function(d, i) {
1368+
expect(Plotly.d3.select(this).text()).toEqual(expected[i]);
1369+
});
1370+
}
1371+
1372+
function assertShapes(expected) {
1373+
var paths = Plotly.d3.select(gd).selectAll('.shapelayer path');
1374+
1375+
expect(expected.length).toEqual(paths.size());
1376+
1377+
paths.each(function(d, i) {
1378+
expect(Plotly.d3.select(this).style('fill')).toEqual(expected[i]);
1379+
});
1380+
}
1381+
1382+
function assertImages(expected) {
1383+
var imgs = Plotly.d3.select(gd).selectAll('.imagelayer image');
1384+
1385+
expect(expected.length).toEqual(imgs.size());
1386+
1387+
imgs.each(function(d, i) {
1388+
expect(Plotly.d3.select(this).attr('href')).toEqual(expected[i]);
1389+
});
1390+
}
1391+
1392+
Plotly.plot(gd,
1393+
[{y: [1, 2, 3]}],
1394+
{
1395+
annotations: [{text: 'hello'}],
1396+
shapes: [{fillcolor: 'rgb(170, 170, 170)'}],
1397+
images: [{source: img1}]
1398+
}
1399+
).then(function() {
1400+
assertAnnotations(['hello']);
1401+
assertShapes(['rgb(170, 170, 170)']);
1402+
assertImages([img1]);
1403+
1404+
return Plotly.animate(gd, [{
1405+
layout: {
1406+
annotations: [{text: 'hi'}],
1407+
shapes: [
1408+
{fillcolor: 'rgb(171, 171, 171)'},
1409+
{fillcolor: 'rgb(172, 172, 172)'}
1410+
],
1411+
images: [{source: img2}]
1412+
}
1413+
}], {
1414+
frame: {redraw: false, duration: 0}
1415+
});
1416+
}).then(function() {
1417+
assertAnnotations(['hi']);
1418+
assertShapes([
1419+
'rgb(171, 171, 171)',
1420+
'rgb(172, 172, 172)'
1421+
]);
1422+
assertImages([img2]);
1423+
1424+
}).catch(failTest).then(done);
1425+
});
1426+
});

0 commit comments

Comments
 (0)