-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Range slider second iteration (part 2: on-par range plots !!!) #1017
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 all commits
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 |
---|---|---|
|
@@ -12,14 +12,18 @@ var d3 = require('d3'); | |
|
||
var Plotly = require('../../plotly'); | ||
var Plots = require('../../plots/plots'); | ||
var Axes = require('../../plots/cartesian/axes'); | ||
|
||
var Lib = require('../../lib'); | ||
var Drawing = require('../drawing'); | ||
var Color = require('../color'); | ||
|
||
var Cartesian = require('../../plots/cartesian'); | ||
var Axes = require('../../plots/cartesian/axes'); | ||
|
||
var dragElement = require('../dragelement'); | ||
var setCursor = require('../../lib/setcursor'); | ||
|
||
var constants = require('./constants'); | ||
var rangePlot = require('./range_plot'); | ||
|
||
|
||
module.exports = function(gd) { | ||
|
@@ -55,7 +59,14 @@ module.exports = function(gd) { | |
.classed(constants.containerClassName, true) | ||
.attr('pointer-events', 'all'); | ||
|
||
rangeSliders.exit().remove(); | ||
// remove exiting sliders and their corresponding clip paths | ||
rangeSliders.exit().each(function(axisOpts) { | ||
var rangeSlider = d3.select(this), | ||
opts = axisOpts[constants.name]; | ||
|
||
rangeSlider.remove(); | ||
fullLayout._topdefs.select('#' + opts._clipId).remove(); | ||
}); | ||
|
||
// remove push margin object(s) | ||
if(rangeSliders.exit().size()) clearPushMargins(gd); | ||
|
@@ -82,6 +93,8 @@ module.exports = function(gd) { | |
domain = axisOpts.domain; | ||
|
||
opts._id = constants.name + axisOpts._id; | ||
opts._clipId = opts._id + '-' + fullLayout._uid; | ||
|
||
opts._width = graphSize.w * (domain[1] - domain[0]); | ||
opts._height = (fullLayout.height - margin.b - margin.t) * opts.thickness; | ||
opts._offsetShift = Math.floor(opts.borderwidth / 2); | ||
|
@@ -95,6 +108,7 @@ module.exports = function(gd) { | |
|
||
rangeSlider | ||
.call(drawBg, gd, axisOpts, opts) | ||
.call(addClipPath, gd, axisOpts, opts) | ||
.call(drawRangePlot, gd, axisOpts, opts) | ||
.call(drawMasks, gd, axisOpts, opts) | ||
.call(drawSlideBox, gd, axisOpts, opts) | ||
|
@@ -279,17 +293,102 @@ function drawBg(rangeSlider, gd, axisOpts, opts) { | |
}); | ||
} | ||
|
||
function drawRangePlot(rangeSlider, gd, axisOpts, opts) { | ||
var rangePlots = rangePlot(gd, opts._width, opts._height); | ||
function addClipPath(rangeSlider, gd, axisOpts, opts) { | ||
var fullLayout = gd._fullLayout; | ||
|
||
var gRangePlot = rangeSlider.selectAll('g.' + constants.rangePlotClassName) | ||
var clipPath = fullLayout._topdefs.selectAll('#' + opts._clipId) | ||
.data([0]); | ||
|
||
gRangePlot.enter().append('g') | ||
.classed(constants.rangePlotClassName, true); | ||
clipPath.enter().append('clipPath') | ||
.attr('id', opts._clipId) | ||
.append('rect') | ||
.attr({ x: 0, y: 0 }); | ||
|
||
clipPath.select('rect').attr({ | ||
width: opts._width, | ||
height: opts._height | ||
}); | ||
} | ||
|
||
function drawRangePlot(rangeSlider, gd, axisOpts, opts) { | ||
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. So, the algorithm is as follows:
|
||
var subplotData = Axes.getSubplots(gd, axisOpts), | ||
calcData = gd.calcdata; | ||
|
||
var rangePlots = rangeSlider.selectAll('g.' + constants.rangePlotClassName) | ||
.data(subplotData, Lib.identity); | ||
|
||
rangePlots.enter().append('g') | ||
.attr('class', function(id) { return constants.rangePlotClassName + ' ' + id; }) | ||
.call(Drawing.setClipUrl, opts._clipId); | ||
|
||
rangePlots.order(); | ||
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. The order is important to manage (and easy to neglect) with all of these d3 joins. |
||
|
||
rangePlots.exit().remove(); | ||
|
||
var mainplotinfo; | ||
|
||
rangePlots.each(function(id, i) { | ||
var plotgroup = d3.select(this), | ||
isMainPlot = (i === 0); | ||
|
||
var oppAxisOpts = Axes.getFromId(gd, id, 'y'), | ||
oppAxisName = oppAxisOpts._name; | ||
|
||
var mockFigure = { | ||
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. Interesting. There's something I always like the usage of |
||
data: [], | ||
layout: { | ||
xaxis: { | ||
domain: [0, 1], | ||
range: opts.range.slice() | ||
}, | ||
width: opts._width, | ||
height: opts._height, | ||
margin: { t: 0, b: 0, l: 0, r: 0 } | ||
} | ||
}; | ||
|
||
mockFigure.layout[oppAxisName] = { | ||
domain: [0, 1], | ||
range: oppAxisOpts.range.slice() | ||
}; | ||
|
||
Plots.supplyDefaults(mockFigure); | ||
|
||
var xa = mockFigure._fullLayout.xaxis, | ||
ya = mockFigure._fullLayout[oppAxisName]; | ||
|
||
var plotinfo = { | ||
id: id, | ||
plotgroup: plotgroup, | ||
xaxis: xa, | ||
yaxis: ya | ||
}; | ||
|
||
if(isMainPlot) mainplotinfo = plotinfo; | ||
else { | ||
plotinfo.mainplot = 'xy'; | ||
plotinfo.mainplotinfo = mainplotinfo; | ||
} | ||
|
||
Cartesian.rangePlot(gd, plotinfo, filterRangePlotCalcData(calcData, id)); | ||
|
||
if(isMainPlot) plotinfo.bg.call(Color.fill, opts.bgcolor); | ||
}); | ||
} | ||
|
||
function filterRangePlotCalcData(calcData, subplotId) { | ||
var out = []; | ||
|
||
for(var i = 0; i < calcData.length; i++) { | ||
var calcTrace = calcData[i], | ||
trace = calcTrace[0].trace; | ||
|
||
if(trace.xaxis + trace.yaxis === subplotId) { | ||
out.push(calcTrace); | ||
} | ||
} | ||
|
||
gRangePlot.html(null); | ||
gRangePlot.node().appendChild(rangePlots); | ||
return out; | ||
} | ||
|
||
function drawMasks(rangeSlider, gd, axisOpts, opts) { | ||
|
This file was deleted.
This file was deleted.
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.
Did you manage to factor out the
.data([0])
pattern? I suppose it would be a function with a name likevar clipPath = createOrAppend(fullLayout._topdefs, '#' + opts._clipId);
?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.
Not yet. I'll do that in a PR of its own. Hopefully this week.