-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
fix layer ordering of scatter subtypes #2978
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
Changes from 2 commits
aeef7f7
7c54fc2
509ed7e
6988818
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,8 @@ var d3 = require('d3'); | |
|
||
var Registry = require('../../registry'); | ||
var Lib = require('../../lib'); | ||
var ensureSingle = Lib.ensureSingle; | ||
var identity = Lib.identity; | ||
var Drawing = require('../../components/drawing'); | ||
|
||
var subTypes = require('./subtypes'); | ||
|
@@ -43,7 +45,7 @@ module.exports = function plot(gd, plotinfo, cdscatter, scatterLayer, transition | |
// the z-order of fill layers is correct. | ||
linkTraces(gd, plotinfo, cdscatter); | ||
|
||
createFills(gd, scatterLayer, plotinfo); | ||
createFills(gd, join, plotinfo); | ||
|
||
// Sort the traces, once created, so that the ordering is preserved even when traces | ||
// are shown and hidden. This is needed since we're not just wiping everything out | ||
|
@@ -52,10 +54,10 @@ module.exports = function plot(gd, plotinfo, cdscatter, scatterLayer, transition | |
uids[cdscatter[i][0].trace.uid] = i; | ||
} | ||
|
||
scatterLayer.selectAll('g.trace').sort(function(a, b) { | ||
join.sort(function(a, b) { | ||
var idx1 = uids[a[0].trace.uid]; | ||
var idx2 = uids[b[0].trace.uid]; | ||
return idx1 > idx2 ? 1 : -1; | ||
return idx1 - idx2; | ||
}); | ||
|
||
if(hasTransition) { | ||
|
@@ -97,51 +99,45 @@ module.exports = function plot(gd, plotinfo, cdscatter, scatterLayer, transition | |
scatterLayer.selectAll('path:not([d])').remove(); | ||
}; | ||
|
||
function createFills(gd, scatterLayer, plotinfo) { | ||
var trace; | ||
function createFills(gd, traceJoin, plotinfo) { | ||
traceJoin.each(function(d) { | ||
var fills = ensureSingle(d3.select(this), 'g', 'fills'); | ||
Drawing.setClipUrl(fills, plotinfo.layerClipId); | ||
|
||
scatterLayer.selectAll('g.trace').each(function(d) { | ||
var tr = d3.select(this); | ||
|
||
// Loop only over the traces being redrawn: | ||
trace = d[0].trace; | ||
var trace = d[0].trace; | ||
|
||
// make the fill-to-next path now for the NEXT trace, so it shows | ||
// behind both lines. | ||
var fillData = []; | ||
if(trace.fill && (trace.fill.substr(0, 6) === 'tozero' || trace.fill === 'toself' || | ||
(trace.fill.substr(0, 2) === 'to' && !trace._prevtrace)) | ||
) { | ||
fillData = ['_ownFill']; | ||
} | ||
if(trace._nexttrace) { | ||
trace._nextFill = tr.select('.js-fill.js-tonext'); | ||
if(!trace._nextFill.size()) { | ||
// make the fill-to-next path now for the NEXT trace, so it shows | ||
// behind both lines. | ||
fillData.push('_nextFill'); | ||
} | ||
|
||
// If there is an existing tozero fill, we must insert this *after* that fill: | ||
var loc = ':first-child'; | ||
if(tr.select('.js-fill.js-tozero').size()) { | ||
loc += ' + *'; | ||
} | ||
var fillJoin = fills.selectAll('g') | ||
.data(fillData, identity); | ||
|
||
trace._nextFill = tr.insert('path', loc).attr('class', 'js-fill js-tonext'); | ||
} | ||
} else { | ||
tr.selectAll('.js-fill.js-tonext').remove(); | ||
trace._nextFill = null; | ||
} | ||
fillJoin.enter().append('g'); | ||
|
||
if(trace.fill && (trace.fill.substr(0, 6) === 'tozero' || trace.fill === 'toself' || | ||
(trace.fill.substr(0, 2) === 'to' && !trace._prevtrace))) { | ||
trace._ownFill = tr.select('.js-fill.js-tozero'); | ||
if(!trace._ownFill.size()) { | ||
trace._ownFill = tr.insert('path', ':first-child').attr('class', 'js-fill js-tozero'); | ||
} | ||
} else { | ||
tr.selectAll('.js-fill.js-tozero').remove(); | ||
trace._ownFill = null; | ||
} | ||
fillJoin.exit() | ||
.each(function(d) { trace[d] = null; }) | ||
.remove(); | ||
|
||
tr.selectAll('.js-fill').call(Drawing.setClipUrl, plotinfo.layerClipId); | ||
fillJoin.order().each(function(d) { | ||
// make a path element inside the fill group, just so | ||
// we can give it its own data later on and the group can | ||
// keep its simple '_*Fill' data | ||
trace[d] = ensureSingle(d3.select(this), 'path', 'js-fill'); | ||
}); | ||
}); | ||
} | ||
|
||
function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transitionOpts) { | ||
var join, i; | ||
var i; | ||
|
||
// Since this has been reorganized and we're executing this on individual traces, | ||
// we need to pass it the full list of cdscatter as well as this trace's index (idx) | ||
|
@@ -157,12 +153,17 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition | |
var xa = plotinfo.xaxis, | ||
ya = plotinfo.yaxis; | ||
|
||
var trace = cdscatter[0].trace, | ||
line = trace.line, | ||
tr = d3.select(element); | ||
var trace = cdscatter[0].trace; | ||
var line = trace.line; | ||
var tr = d3.select(element); | ||
|
||
var errorBarGroup = ensureSingle(tr, 'g', 'errorbars'); | ||
var lines = ensureSingle(tr, 'g', 'lines'); | ||
var points = ensureSingle(tr, 'g', 'points'); | ||
var text = ensureSingle(tr, 'g', 'text'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm. So now all scatter traces (no-matter their What if instead we made a "mode" groups data-bind: var modeData = []
if(trace.error_y.visible || trace.error_x.visible) modeData.push('errorbars');
if(trace.mode.indexOf('lines') !== -1) modeData.push('lines');
if(trace.mode.indexOf('markers') !== -1) modeData.push('points');
if(trace.mode.indexOf('text') !== -1) modeData.push('text');
var modeGroups = tr.selectAll('g.mode'))
.data(modeData, identity);
modeGroups.exit().remove();
modeGroups.enter().append('g')
.classed('mode', true)
.attr('class', identity);
modeGroups.order(); That way those empty There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (discussed offline but for future reference) I tried to do this... and it was going well for a while, but I ran into issues with the fact that various disjoint pathways (eg styling, errorbars) expect the trace data to be attached to these groups. And if you use Anyway, for now we agreed to leave it as is. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
👌 |
||
|
||
// error bars are at the bottom | ||
Registry.getComponentMethod('errorbars', 'plot')(tr, plotinfo, transitionOpts); | ||
Registry.getComponentMethod('errorbars', 'plot')(errorBarGroup, plotinfo, transitionOpts); | ||
|
||
if(trace.visible !== true) return; | ||
|
||
|
@@ -303,7 +304,7 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition | |
}; | ||
} | ||
|
||
var lineJoin = tr.selectAll('.js-line').data(segments); | ||
var lineJoin = lines.selectAll('.js-line').data(segments); | ||
|
||
transition(lineJoin.exit()) | ||
.style('opacity', 0) | ||
|
@@ -325,6 +326,7 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition | |
|
||
if(segments.length) { | ||
if(ownFillEl3) { | ||
ownFillEl3.datum(cdscatter); | ||
if(pt0 && pt1) { | ||
if(ownFillDir) { | ||
if(ownFillDir === 'y') { | ||
|
@@ -404,11 +406,10 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition | |
return false; | ||
} | ||
|
||
function makePoints(d) { | ||
function makePoints(points, text, cdscatter) { | ||
var join, selection, hasNode; | ||
|
||
var trace = d[0].trace; | ||
var s = d3.select(this); | ||
var trace = cdscatter[0].trace; | ||
var showMarkers = subTypes.hasMarkers(trace); | ||
var showText = subTypes.hasText(trace); | ||
|
||
|
@@ -417,16 +418,16 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition | |
var textFilter = hideFilter; | ||
|
||
if(showMarkers) { | ||
markerFilter = (trace.marker.maxdisplayed || trace._needsCull) ? visFilter : Lib.identity; | ||
markerFilter = (trace.marker.maxdisplayed || trace._needsCull) ? visFilter : identity; | ||
} | ||
|
||
if(showText) { | ||
textFilter = (trace.marker.maxdisplayed || trace._needsCull) ? visFilter : Lib.identity; | ||
textFilter = (trace.marker.maxdisplayed || trace._needsCull) ? visFilter : identity; | ||
} | ||
|
||
// marker points | ||
|
||
selection = s.selectAll('path.point'); | ||
selection = points.selectAll('path.point'); | ||
|
||
join = selection.data(markerFilter, keyFunc); | ||
|
||
|
@@ -478,7 +479,7 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition | |
} | ||
|
||
// text points | ||
selection = s.selectAll('g'); | ||
selection = text.selectAll('g'); | ||
join = selection.data(textFilter, keyFunc); | ||
|
||
// each text needs to go in its own 'g' in case | ||
|
@@ -517,28 +518,16 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition | |
join.exit().remove(); | ||
} | ||
|
||
// NB: selectAll is evaluated on instantiation: | ||
var pointSelection = tr.selectAll('.points'); | ||
|
||
// Join with new data | ||
join = pointSelection.data([cdscatter]); | ||
|
||
// Transition existing, but don't defer this to an async .transition since | ||
// there's no timing involved: | ||
pointSelection.each(makePoints); | ||
|
||
join.enter().append('g') | ||
.classed('points', true) | ||
.each(makePoints); | ||
|
||
join.exit().remove(); | ||
points.datum(cdscatter); | ||
text.datum(cdscatter); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice use of |
||
makePoints(points, text, cdscatter); | ||
|
||
// lastly, clip points groups of `cliponaxis !== false` traces | ||
// on `plotinfo._hasClipOnAxisFalse === true` subplots | ||
join.each(function(d) { | ||
var hasClipOnAxisFalse = d[0].trace.cliponaxis === false; | ||
Drawing.setClipUrl(d3.select(this), hasClipOnAxisFalse ? null : plotinfo.layerClipId); | ||
}); | ||
var hasClipOnAxisFalse = trace.cliponaxis === false; | ||
var clipUrl = hasClipOnAxisFalse ? null : plotinfo.layerClipId; | ||
Drawing.setClipUrl(points, clipUrl); | ||
Drawing.setClipUrl(text, clipUrl); | ||
} | ||
|
||
function selectMarkers(gd, idx, plotinfo, cdscatter, cdscatterAll) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,12 @@ function style(gd, cd) { | |
stylePoints(sel, trace, gd); | ||
}); | ||
|
||
s.selectAll('g.text').each(function(d) { | ||
var sel = d3.select(this); | ||
var trace = d.trace || d[0].trace; | ||
styleText(sel, trace, gd); | ||
}); | ||
|
||
s.selectAll('g.trace path.js-line') | ||
.call(Drawing.lineGroupStyle); | ||
|
||
|
@@ -37,6 +43,9 @@ function style(gd, cd) { | |
|
||
function stylePoints(sel, trace, gd) { | ||
Drawing.pointStyle(sel.selectAll('path.point'), trace, gd); | ||
} | ||
|
||
function styleText(sel, trace, gd) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Previously text was just shoved into the same group as points, which had the pleasant side-effect of letting them be styled together. Now that they're in separate groups they need independent outer selections. AFAICT none of the other users of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh hmm, I guess the image failure is telling me There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. alright, put back into scatterGeo -> 7c54fc2 Note that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Glad to see our tests caught that. Now that only scattergeo uses it, maybe we could move https://github.com/plotly/plotly.js/blob/master/src/traces/scattergeo/style.js ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah never mind, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
👍 for having text and points in different groups! |
||
Drawing.textPointStyle(sel.selectAll('text'), trace, gd); | ||
} | ||
|
||
|
@@ -49,11 +58,13 @@ function styleOnSelect(gd, cd) { | |
Drawing.selectedTextStyle(s.selectAll('text'), trace); | ||
} else { | ||
stylePoints(s, trace, gd); | ||
styleText(s, trace, gd); | ||
} | ||
} | ||
|
||
module.exports = { | ||
style: style, | ||
stylePoints: stylePoints, | ||
styleText: styleText, | ||
styleOnSelect: styleOnSelect | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A little hard to tell from the diff, but wow
createFills
is so much cleaner now. 🥇