Skip to content

Commit 28f4a05

Browse files
authored
Merge pull request #1616 from plotly/text-layout-transition
Inverse-transform text on layout transition
2 parents 132c8ea + c7cdc8b commit 28f4a05

File tree

5 files changed

+74
-4
lines changed

5 files changed

+74
-4
lines changed

src/components/drawing/index.js

+30
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,36 @@ drawing.setPointGroupScale = function(selection, x, y) {
769769
return scale;
770770
};
771771

772+
var TEXT_POINT_LAST_TRANSLATION_RE = /translate\([^)]*\)\s*$/;
773+
774+
drawing.setTextPointsScale = function(selection, xScale, yScale) {
775+
selection.each(function() {
776+
var transforms;
777+
var el = d3.select(this);
778+
var text = el.select('text');
779+
var x = parseFloat(text.attr('x') || 0);
780+
var y = parseFloat(text.attr('y') || 0);
781+
782+
var existingTransform = (el.attr('transform') || '').match(TEXT_POINT_LAST_TRANSLATION_RE);
783+
784+
if(xScale === 1 && yScale === 1) {
785+
transforms = [];
786+
} else {
787+
transforms = [
788+
'translate(' + x + ',' + y + ')',
789+
'scale(' + xScale + ',' + yScale + ')',
790+
'translate(' + (-x) + ',' + (-y) + ')',
791+
];
792+
}
793+
794+
if(existingTransform) {
795+
transforms.push(existingTransform);
796+
}
797+
798+
el.attr('transform', transforms.join(' '));
799+
});
800+
};
801+
772802
drawing.measureText = function(tester, text, font) {
773803
var dummyText = tester.append('text')
774804
.text(text)

src/plots/cartesian/dragbox.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ var constants = require('./constants');
3030
var MINDRAG = constants.MINDRAG;
3131
var MINZOOM = constants.MINZOOM;
3232

33-
3433
// flag for showing "doubleclick to zoom out" only at the beginning
3534
var SHOWZOOMOUTTIP = true;
3635

@@ -747,6 +746,10 @@ module.exports = function dragBox(gd, plotinfo, x, y, w, h, ns, ew) {
747746
// as a whole:
748747
.select('.scatterlayer').selectAll('.points').selectAll('.point')
749748
.call(Drawing.setPointGroupScale, xScaleFactor2, yScaleFactor2);
749+
750+
subplot.plot.select('.scatterlayer')
751+
.selectAll('.points').selectAll('.textpoint')
752+
.call(Drawing.setTextPointsScale, xScaleFactor2, yScaleFactor2);
750753
}
751754
}
752755

src/plots/cartesian/transition_axes.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,11 @@ module.exports = function transitionAxes(gd, newLayout, transitionOpts, makeOnCo
148148
// This is specifically directed at scatter traces, applying an inverse
149149
// scale to individual points to counteract the scale of the trace
150150
// as a whole:
151-
.selectAll('.points').selectAll('.point')
151+
.select('.scatterlayer').selectAll('.points').selectAll('.point')
152152
.call(Drawing.setPointGroupScale, 1, 1);
153153

154+
subplot.plot.select('.scatterlayer').selectAll('.points').selectAll('.textpoint')
155+
.call(Drawing.setTextPointsScale, 1, 1);
154156
}
155157

156158
function updateSubplot(subplot, progress) {
@@ -229,6 +231,8 @@ module.exports = function transitionAxes(gd, newLayout, transitionOpts, makeOnCo
229231
.selectAll('.points').selectAll('.point')
230232
.call(Drawing.setPointGroupScale, 1 / xScaleFactor, 1 / yScaleFactor);
231233

234+
subplot.plot.selectAll('.points').selectAll('.textpoint')
235+
.call(Drawing.setTextPointsScale, 1 / xScaleFactor, 1 / yScaleFactor);
232236
}
233237

234238
var onComplete;

src/traces/scatter/plot.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -455,15 +455,14 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
455455

456456
// each text needs to go in its own 'g' in case
457457
// it gets converted to mathjax
458-
join.enter().append('g').append('text');
458+
join.enter().append('g').classed('textpoint', true).append('text');
459459

460460
join.each(function(d) {
461461
var sel = transition(d3.select(this).select('text'));
462462
Drawing.translatePoint(d, sel, xa, ya);
463463
});
464464

465465
join.selectAll('text')
466-
.classed('textpoint', true)
467466
.call(Drawing.textPointStyle, trace)
468467
.each(function(d) {
469468

test/jasmine/tests/drawing_test.js

+34
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,40 @@ describe('Drawing', function() {
314314
expect(el.getAttribute('transform')).toBe('translate(1,2)');
315315
});
316316
});
317+
318+
describe('setTextPointsScale', function() {
319+
var svg, g, text;
320+
321+
beforeEach(function() {
322+
svg = d3.select(document.createElement('svg'));
323+
g = svg.append('g');
324+
text = g.append('text');
325+
});
326+
327+
it('sets the transform on an empty element', function() {
328+
Drawing.setTextPointsScale(g, 2, 3);
329+
expect(g.attr('transform')).toEqual('translate(0,0) scale(2,3) translate(0,0)');
330+
});
331+
332+
it('unsets the transform', function() {
333+
Drawing.setTextPointsScale(g, 1, 1);
334+
expect(g.attr('transform')).toEqual('');
335+
});
336+
337+
it('preserves a leading translate', function() {
338+
Drawing.setTextPointsScale(g, 1, 1);
339+
g.attr('transform', 'translate(1, 2)');
340+
expect(g.attr('transform')).toEqual('translate(1, 2)');
341+
});
342+
343+
it('preserves transforms', function() {
344+
text.attr('x', 8);
345+
text.attr('y', 9);
346+
g.attr('transform', 'translate(1, 2)');
347+
Drawing.setTextPointsScale(g, 4, 5);
348+
expect(g.attr('transform')).toEqual('translate(8,9) scale(4,5) translate(-8,-9) translate(1, 2)');
349+
});
350+
});
317351
});
318352

319353
describe('gradients', function() {

0 commit comments

Comments
 (0)