From 3cb8cadce9cb79d4889995b55b320e85361767bd Mon Sep 17 00:00:00 2001 From: Ricky Reusser Date: Wed, 5 Oct 2016 12:56:03 -0400 Subject: [PATCH 1/3] Adjust d3 update to enable text mode animation --- src/components/drawing/index.js | 92 ++++++++++++++++++--------------- src/traces/scatter/plot.js | 14 +++-- 2 files changed, 58 insertions(+), 48 deletions(-) diff --git a/src/components/drawing/index.js b/src/components/drawing/index.js index cface72c6e9..073eacfc897 100644 --- a/src/components/drawing/index.js +++ b/src/components/drawing/index.js @@ -339,51 +339,57 @@ drawing.tryColorscale = function(cont, contIn, prefix) { // draw text at points var TEXTOFFSETSIGN = {start: 1, end: -1, middle: 0, bottom: 1, top: -1}, LINEEXPAND = 1.3; + +drawing.singleTextPointStyle = function(d, sel, trace) { + var el = sel.node(), + text = d.tx || trace.text; + + if(!text || Array.isArray(text)) { + // isArray test handles the case of (intentionally) missing + // or empty text within a text array + sel.remove(); + return; + } + + var pos = d.tp || trace.textposition, + v = pos.indexOf('top') !== -1 ? 'top' : + pos.indexOf('bottom') !== -1 ? 'bottom' : 'middle', + h = pos.indexOf('left') !== -1 ? 'end' : + pos.indexOf('right') !== -1 ? 'start' : 'middle', + fontSize = d.ts || trace.textfont.size, + // if markers are shown, offset a little more than + // the nominal marker size + // ie 2/1.6 * nominal, bcs some markers are a bit bigger + r = d.mrc ? (d.mrc / 0.8 + 1) : 0; + + fontSize = (isNumeric(fontSize) && fontSize > 0) ? fontSize : 0; + + sel.call(drawing.font, + d.tf || trace.textfont.family, + fontSize, + d.tc || trace.textfont.color) + .attr('text-anchor', h) + .text(text) + .call(svgTextUtils.convertToTspans); + var pgroup = d3.select(el.parentNode), + tspans = sel.selectAll('tspan.line'), + numLines = ((tspans[0].length || 1) - 1) * LINEEXPAND + 1, + dx = TEXTOFFSETSIGN[h] * r, + dy = fontSize * 0.75 + TEXTOFFSETSIGN[v] * r + + (TEXTOFFSETSIGN[v] - 1) * numLines * fontSize / 2; + + // fix the overall text group position + pgroup.attr('transform', 'translate(' + dx + ',' + dy + ')'); + + // then fix multiline text + if(numLines > 1) { + tspans.attr({ x: sel.attr('x'), y: sel.attr('y') }); + } +}; + drawing.textPointStyle = function(s, trace) { s.each(function(d) { - var p = d3.select(this), - text = d.tx || trace.text; - if(!text || Array.isArray(text)) { - // isArray test handles the case of (intentionally) missing - // or empty text within a text array - p.remove(); - return; - } - - var pos = d.tp || trace.textposition, - v = pos.indexOf('top') !== -1 ? 'top' : - pos.indexOf('bottom') !== -1 ? 'bottom' : 'middle', - h = pos.indexOf('left') !== -1 ? 'end' : - pos.indexOf('right') !== -1 ? 'start' : 'middle', - fontSize = d.ts || trace.textfont.size, - // if markers are shown, offset a little more than - // the nominal marker size - // ie 2/1.6 * nominal, bcs some markers are a bit bigger - r = d.mrc ? (d.mrc / 0.8 + 1) : 0; - - fontSize = (isNumeric(fontSize) && fontSize > 0) ? fontSize : 0; - - p.call(drawing.font, - d.tf || trace.textfont.family, - fontSize, - d.tc || trace.textfont.color) - .attr('text-anchor', h) - .text(text) - .call(svgTextUtils.convertToTspans); - var pgroup = d3.select(this.parentNode), - tspans = p.selectAll('tspan.line'), - numLines = ((tspans[0].length || 1) - 1) * LINEEXPAND + 1, - dx = TEXTOFFSETSIGN[h] * r, - dy = fontSize * 0.75 + TEXTOFFSETSIGN[v] * r + - (TEXTOFFSETSIGN[v] - 1) * numLines * fontSize / 2; - - // fix the overall text group position - pgroup.attr('transform', 'translate(' + dx + ',' + dy + ')'); - - // then fix multiline text - if(numLines > 1) { - tspans.attr({ x: p.attr('x'), y: p.attr('y') }); - } + drawing.singleTextPointStyle(d, d3.select(this), trace); }); }; diff --git a/src/traces/scatter/plot.js b/src/traces/scatter/plot.js index 763a42cff7f..2c3aabd77c5 100644 --- a/src/traces/scatter/plot.js +++ b/src/traces/scatter/plot.js @@ -443,18 +443,22 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition } // text points - selection = s.selectAll('g'); - join = selection.data(textFilter, keyFunc); // each text needs to go in its own 'g' in case // it gets converted to mathjax - join.enter().append('g') - .append('text'); + enter = join.enter().append('g') + .append('text') + .call(Drawing.textPointStyle, trace); join.each(function(d) { - var sel = d3.select(this).select('text'); + var node = d3.select(this).select('text'); + // We can't transition the text itself, so call this on the node: + Drawing.singleTextPointStyle(d, node, trace); + + // This duck-types the node to be set either as a transition or as a node: + var sel = transition(node); Drawing.translatePoint(d, sel, xa, ya); }); From 4f3f0a63fc5ecfeac321c57aa364b954591679fd Mon Sep 17 00:00:00 2001 From: Ricky Reusser Date: Wed, 5 Oct 2016 13:13:34 -0400 Subject: [PATCH 2/3] Remove unnecessary text style refactoring --- src/components/drawing/index.js | 92 +++++++++++++++------------------ src/traces/scatter/plot.js | 14 ++--- 2 files changed, 48 insertions(+), 58 deletions(-) diff --git a/src/components/drawing/index.js b/src/components/drawing/index.js index 073eacfc897..cface72c6e9 100644 --- a/src/components/drawing/index.js +++ b/src/components/drawing/index.js @@ -339,57 +339,51 @@ drawing.tryColorscale = function(cont, contIn, prefix) { // draw text at points var TEXTOFFSETSIGN = {start: 1, end: -1, middle: 0, bottom: 1, top: -1}, LINEEXPAND = 1.3; - -drawing.singleTextPointStyle = function(d, sel, trace) { - var el = sel.node(), - text = d.tx || trace.text; - - if(!text || Array.isArray(text)) { - // isArray test handles the case of (intentionally) missing - // or empty text within a text array - sel.remove(); - return; - } - - var pos = d.tp || trace.textposition, - v = pos.indexOf('top') !== -1 ? 'top' : - pos.indexOf('bottom') !== -1 ? 'bottom' : 'middle', - h = pos.indexOf('left') !== -1 ? 'end' : - pos.indexOf('right') !== -1 ? 'start' : 'middle', - fontSize = d.ts || trace.textfont.size, - // if markers are shown, offset a little more than - // the nominal marker size - // ie 2/1.6 * nominal, bcs some markers are a bit bigger - r = d.mrc ? (d.mrc / 0.8 + 1) : 0; - - fontSize = (isNumeric(fontSize) && fontSize > 0) ? fontSize : 0; - - sel.call(drawing.font, - d.tf || trace.textfont.family, - fontSize, - d.tc || trace.textfont.color) - .attr('text-anchor', h) - .text(text) - .call(svgTextUtils.convertToTspans); - var pgroup = d3.select(el.parentNode), - tspans = sel.selectAll('tspan.line'), - numLines = ((tspans[0].length || 1) - 1) * LINEEXPAND + 1, - dx = TEXTOFFSETSIGN[h] * r, - dy = fontSize * 0.75 + TEXTOFFSETSIGN[v] * r + - (TEXTOFFSETSIGN[v] - 1) * numLines * fontSize / 2; - - // fix the overall text group position - pgroup.attr('transform', 'translate(' + dx + ',' + dy + ')'); - - // then fix multiline text - if(numLines > 1) { - tspans.attr({ x: sel.attr('x'), y: sel.attr('y') }); - } -}; - drawing.textPointStyle = function(s, trace) { s.each(function(d) { - drawing.singleTextPointStyle(d, d3.select(this), trace); + var p = d3.select(this), + text = d.tx || trace.text; + if(!text || Array.isArray(text)) { + // isArray test handles the case of (intentionally) missing + // or empty text within a text array + p.remove(); + return; + } + + var pos = d.tp || trace.textposition, + v = pos.indexOf('top') !== -1 ? 'top' : + pos.indexOf('bottom') !== -1 ? 'bottom' : 'middle', + h = pos.indexOf('left') !== -1 ? 'end' : + pos.indexOf('right') !== -1 ? 'start' : 'middle', + fontSize = d.ts || trace.textfont.size, + // if markers are shown, offset a little more than + // the nominal marker size + // ie 2/1.6 * nominal, bcs some markers are a bit bigger + r = d.mrc ? (d.mrc / 0.8 + 1) : 0; + + fontSize = (isNumeric(fontSize) && fontSize > 0) ? fontSize : 0; + + p.call(drawing.font, + d.tf || trace.textfont.family, + fontSize, + d.tc || trace.textfont.color) + .attr('text-anchor', h) + .text(text) + .call(svgTextUtils.convertToTspans); + var pgroup = d3.select(this.parentNode), + tspans = p.selectAll('tspan.line'), + numLines = ((tspans[0].length || 1) - 1) * LINEEXPAND + 1, + dx = TEXTOFFSETSIGN[h] * r, + dy = fontSize * 0.75 + TEXTOFFSETSIGN[v] * r + + (TEXTOFFSETSIGN[v] - 1) * numLines * fontSize / 2; + + // fix the overall text group position + pgroup.attr('transform', 'translate(' + dx + ',' + dy + ')'); + + // then fix multiline text + if(numLines > 1) { + tspans.attr({ x: p.attr('x'), y: p.attr('y') }); + } }); }; diff --git a/src/traces/scatter/plot.js b/src/traces/scatter/plot.js index 2c3aabd77c5..6edce76549a 100644 --- a/src/traces/scatter/plot.js +++ b/src/traces/scatter/plot.js @@ -448,20 +448,16 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition // each text needs to go in its own 'g' in case // it gets converted to mathjax - enter = join.enter().append('g') - .append('text') - .call(Drawing.textPointStyle, trace); + join.enter().append('g').append('text'); join.each(function(d) { - var node = d3.select(this).select('text'); - // We can't transition the text itself, so call this on the node: - Drawing.singleTextPointStyle(d, node, trace); - - // This duck-types the node to be set either as a transition or as a node: - var sel = transition(node); + var sel = transition(d3.select(this).select('text')); Drawing.translatePoint(d, sel, xa, ya); }); + join.selectAll('text') + .call(Drawing.textPointStyle, trace); + join.exit().remove(); } From 2ca24435d430675c5884d12d6f1a4593f60c27b7 Mon Sep 17 00:00:00 2001 From: Ricky Reusser Date: Wed, 5 Oct 2016 14:39:19 -0400 Subject: [PATCH 3/3] *Make* multiline tspans work correctly --- src/components/drawing/index.js | 1 + src/traces/scatter/plot.js | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/components/drawing/index.js b/src/components/drawing/index.js index cface72c6e9..b4f1c5581e5 100644 --- a/src/components/drawing/index.js +++ b/src/components/drawing/index.js @@ -343,6 +343,7 @@ drawing.textPointStyle = function(s, trace) { s.each(function(d) { var p = d3.select(this), text = d.tx || trace.text; + if(!text || Array.isArray(text)) { // isArray test handles the case of (intentionally) missing // or empty text within a text array diff --git a/src/traces/scatter/plot.js b/src/traces/scatter/plot.js index 6edce76549a..3a271f28f11 100644 --- a/src/traces/scatter/plot.js +++ b/src/traces/scatter/plot.js @@ -456,7 +456,20 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition }); join.selectAll('text') - .call(Drawing.textPointStyle, trace); + .call(Drawing.textPointStyle, trace) + .each(function(d) { + + // This just *has* to be totally custom becuase of SVG text positioning :( + // It's obviously copied from translatePoint; we just can't use that + // + // put xp and yp into d if pixel scaling is already done + var x = d.xp || xa.c2p(d.x), + y = d.yp || ya.c2p(d.y); + + d3.select(this).selectAll('tspan').each(function() { + transition(d3.select(this)).attr({x: x, y: y}); + }); + }); join.exit().remove(); }