Skip to content

Geo refactor and lasso/select-box selections #2030

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

Merged
merged 42 commits into from
Sep 28, 2017
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
4c1ddb8
Introduce geo 2.0
etpinard Sep 21, 2017
482cca1
merge geo axis attrs module into 'main' layout attr module
etpinard Sep 21, 2017
a0be087
add 'geo.center' + improve defaults & :books:
etpinard Sep 21, 2017
e9efdd0
use relayout in geo modeBar buttons
etpinard Sep 21, 2017
9faa1b1
sync pan/scroll interactions into user/full layout
etpinard Sep 21, 2017
d0ea7c9
adapt scattergeo to new geo layers and projection logic
etpinard Sep 21, 2017
a981eb5
adapt choropleth plot and hover (in preparation for selections)
etpinard Sep 21, 2017
44f56dd
prelim stuff for geo selections
etpinard Sep 21, 2017
e53a908
DRY up select test suite
etpinard Sep 21, 2017
0e22ba0
add scattergeo lasso/select
etpinard Sep 21, 2017
397d47c
add choropleth lasso/select
etpinard Sep 21, 2017
825e24d
resolves #1995 - add a miter limit on scattergeo
etpinard Sep 21, 2017
24c2422
clean up and improve geo defaults tests
etpinard Sep 21, 2017
c2b0f9c
resolves #292 - add mucho test for geo pan/scroll interactions
etpinard Sep 21, 2017
3bd89d3
add one geo base layer update test
etpinard Sep 21, 2017
e59c90b
resolves #1698 - add geo_across-antimeridian mock
etpinard Sep 21, 2017
eaf44a8
resolves #1996 - add `geo_scattergeo-out-of-usa`
etpinard Sep 21, 2017
4d9b566
resolves #1486 - add `geo_centering` mock
etpinard Sep 21, 2017
32a29c7
update conic baselines
etpinard Sep 21, 2017
be59f69
update a few scoped baseline
etpinard Sep 21, 2017
36833d4
update `geo_fill` mock
etpinard Sep 22, 2017
7e5bb41
update baseline to show proper marker.opacity
etpinard Sep 22, 2017
a30beea
update other geo baselines
etpinard Sep 22, 2017
fd5bf11
:hocho: obsolete files and logic
etpinard Sep 22, 2017
ae48369
rename temporary geo2.js -> geo.js :tada:
etpinard Sep 22, 2017
5bc2c71
add 'step' name to failure message
etpinard Sep 25, 2017
ab05990
compute geo.midPt more efficiently
etpinard Sep 25, 2017
ce31666
lint (rename params -> exports)
etpinard Sep 25, 2017
eeee911
use {} instead of [] to identify line & fill layers
etpinard Sep 25, 2017
71c5355
improve selection queries
etpinard Sep 25, 2017
a3df09e
use beforeEach in per-trace select tests
etpinard Sep 25, 2017
05e8194
update across antimeridian mock
etpinard Sep 25, 2017
935e4ac
add jasmine test
etpinard Sep 25, 2017
2488f4b
add per-basePlot-module updateFx methods
etpinard Sep 25, 2017
303de22
add `stroke-miterlimit: 2` to base layer lines
etpinard Sep 25, 2017
9bb7d91
use dragElement.unhover to queued Fx.hover calls
etpinard Sep 26, 2017
1c26ec4
add geo.project and use that in scattergeo hover
etpinard Sep 26, 2017
1d2ce2d
handle invalid geo setting that lead to invalid bounds
etpinard Sep 26, 2017
651399e
fix choropleth hover for countries w/ have polygons that cross -180
etpinard Sep 27, 2017
8f9b75a
add _clips and _topclips <g> in makePlotFramework
etpinard Sep 27, 2017
0089488
lint
etpinard Sep 27, 2017
190c733
fix choropleth hover over Antarctica
etpinard Sep 27, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/annotations/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {

var isSizeConstrained = options.width || options.height;

var annTextClip = fullLayout._defs.select('.clips')
var annTextClip = fullLayout._topclips
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexcjohnson IMPORTANT: Annotation used to put its clips in fulLayout._defs, even though Annotation draws in toppaper. Clip ids are global to the page, so things still work fine (at in Chrome and FF). But, who knows maybe some other browsers don't apply clip ids outside the <svg> where the <defs> is located.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice find! Definitely not the intent, thanks for cleaning that up!

.selectAll('#' + annClipID)
.data(isSizeConstrained ? [0] : []);

Expand Down
12 changes: 9 additions & 3 deletions src/components/fx/layout_defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,17 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {

coerce('hovermode', hovermodeDflt);

// if only mapbox subplots is present on graph,
// if only mapbox or geo subplots is present on graph,
// reset 'zoom' dragmode to 'pan' until 'zoom' is implemented,
// so that the correct modebar button is active
if(layoutOut._has('mapbox') && layoutOut._basePlotModules.length === 1 &&
layoutOut.dragmode === 'zoom') {
var hasMapbox = layoutOut._has('mapbox');
var hasGeo = layoutOut._has('geo');
var len = layoutOut._basePlotModules.length;

if(layoutOut.dragmode === 'zoom' && (
((hasMapbox || hasGeo) && len === 1) ||
(hasMapbox && hasGeo && len === 2)
)) {
layoutOut.dragmode = 'pan';
}
};
Expand Down
65 changes: 35 additions & 30 deletions src/components/modebar/buttons.js
Original file line number Diff line number Diff line change
Expand Up @@ -446,23 +446,24 @@ modeBarButtons.hoverClosestGeo = {
};

function handleGeo(gd, ev) {
var button = ev.currentTarget,
attr = button.getAttribute('data-attr'),
val = button.getAttribute('data-val') || true,
fullLayout = gd._fullLayout,
geoIds = Plots.getSubplotIds(fullLayout, 'geo');
var button = ev.currentTarget;
var attr = button.getAttribute('data-attr');
var val = button.getAttribute('data-val') || true;
var fullLayout = gd._fullLayout;
var geoIds = Plots.getSubplotIds(fullLayout, 'geo');

for(var i = 0; i < geoIds.length; i++) {
var geo = fullLayout[geoIds[i]]._subplot;
var id = geoIds[i];
var geoLayout = fullLayout[id];

if(attr === 'zoom') {
var scale = geo.projection.scale();
var scale = geoLayout.projection.scale;
var newScale = (val === 'in') ? 2 * scale : 0.5 * scale;
geo.projection.scale(newScale);
geo.zoom.scale(newScale);
geo.render();

Plotly.relayout(gd, id + '.projection.scale', newScale);
} else if(attr === 'reset') {
resetView(gd, 'geo');
}
else if(attr === 'reset') geo.zoomReset();
}
}

Expand Down Expand Up @@ -535,8 +536,8 @@ modeBarButtons.resetViews = {
button.setAttribute('data-attr', 'resetLastSave');
handleCamera3d(gd, ev);

// N.B handleCamera3d also triggers a replot for
// geo subplots.
resetView(gd, 'geo');
resetView(gd, 'mapbox');
}
};

Expand Down Expand Up @@ -581,22 +582,26 @@ modeBarButtons.resetViewMapbox = {
attr: 'reset',
icon: Icons.home,
click: function(gd) {
var fullLayout = gd._fullLayout;
var subplotIds = Plots.getSubplotIds(fullLayout, 'mapbox');
var aObj = {};

for(var i = 0; i < subplotIds.length; i++) {
var id = subplotIds[i];
var subplotObj = fullLayout[id]._subplot;
var viewInitial = subplotObj.viewInitial;
var viewKeys = Object.keys(viewInitial);

for(var j = 0; j < viewKeys.length; j++) {
var key = viewKeys[j];
aObj[id + '.' + key] = viewInitial[key];
}
}

Plotly.relayout(gd, aObj);
resetView(gd, 'mapbox');
}
};

function resetView(gd, subplotType) {
var fullLayout = gd._fullLayout;
var subplotIds = Plots.getSubplotIds(fullLayout, subplotType);
var aObj = {};

for(var i = 0; i < subplotIds.length; i++) {
var id = subplotIds[i];
var subplotObj = fullLayout[id]._subplot;
var viewInitial = subplotObj.viewInitial;
var viewKeys = Object.keys(viewInitial);

for(var j = 0; j < viewKeys.length; j++) {
var key = viewKeys[j];
aObj[id + '.' + key] = viewInitial[key];
}
}

Plotly.relayout(gd, aObj);
}
40 changes: 17 additions & 23 deletions src/components/modebar/manage.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,16 @@ module.exports = function manageModeBar(gd) {

// logic behind which buttons are displayed by default
function getButtonGroups(gd, buttonsToRemove, buttonsToAdd) {
var fullLayout = gd._fullLayout,
fullData = gd._fullData;
var fullLayout = gd._fullLayout;
var fullData = gd._fullData;

var hasCartesian = fullLayout._has('cartesian'),
hasGL3D = fullLayout._has('gl3d'),
hasGeo = fullLayout._has('geo'),
hasPie = fullLayout._has('pie'),
hasGL2D = fullLayout._has('gl2d'),
hasTernary = fullLayout._has('ternary'),
hasMapbox = fullLayout._has('mapbox');
var hasCartesian = fullLayout._has('cartesian');
var hasGL3D = fullLayout._has('gl3d');
var hasGeo = fullLayout._has('geo');
var hasPie = fullLayout._has('pie');
var hasGL2D = fullLayout._has('gl2d');
var hasTernary = fullLayout._has('ternary');
var hasMapbox = fullLayout._has('mapbox');

var groups = [];

Expand Down Expand Up @@ -112,18 +112,13 @@ function getButtonGroups(gd, buttonsToRemove, buttonsToAdd) {
addGroup(['hoverClosest3d']);
}

if(hasGeo) {
addGroup(['zoomInGeo', 'zoomOutGeo', 'resetGeo']);
addGroup(['hoverClosestGeo']);
}

var allAxesFixed = areAllAxesFixed(fullLayout),
dragModeGroup = [];

if(((hasCartesian || hasGL2D) && !allAxesFixed) || hasTernary) {
dragModeGroup = ['zoom2d', 'pan2d'];
}
if(hasMapbox) {
if(hasMapbox || hasGeo) {
dragModeGroup = ['pan2d'];
}
if(isSelectable(fullData)) {
Expand All @@ -138,18 +133,17 @@ function getButtonGroups(gd, buttonsToRemove, buttonsToAdd) {

if(hasCartesian && hasPie) {
addGroup(['toggleHover']);
}
else if(hasGL2D) {
} else if(hasGL2D) {
addGroup(['hoverClosestGl2d']);
}
else if(hasCartesian) {
} else if(hasCartesian) {
addGroup(['toggleSpikelines', 'hoverClosestCartesian', 'hoverCompareCartesian']);
}
else if(hasPie) {
} else if(hasPie) {
addGroup(['hoverClosestPie']);
}
else if(hasMapbox) {
} else if(hasMapbox) {
addGroup(['resetViewMapbox', 'toggleHover']);
} else if(hasGeo) {
addGroup(['zoomInGeo', 'zoomOutGeo', 'resetGeo']);
addGroup(['hoverClosestGeo']);
}

return appendButtonsToGroups(groups, buttonsToAdd);
Expand Down
15 changes: 0 additions & 15 deletions src/lib/array_to_calc_item.js

This file was deleted.

36 changes: 8 additions & 28 deletions src/lib/geojson_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,70 +54,50 @@ exports.calcTraceToLineCoords = function(calcTrace) {
*
* @param {array} coords
* results form calcTraceToLineCoords
* @param {object} trace
* (optional) full trace object to be added on to output
*
* @return {object} out
* GeoJSON object
*
*/
exports.makeLine = function(coords, trace) {
var out = {};

exports.makeLine = function(coords) {
if(coords.length === 1) {
out = {
return {
type: 'LineString',
coordinates: coords[0]
};
}
else {
out = {
} else {
return {
type: 'MultiLineString',
coordinates: coords
};
}

if(trace) out.trace = trace;

return out;
};

/**
* Make polygon ('Polygon' or 'MultiPolygon') GeoJSON
*
* @param {array} coords
* results form calcTraceToLineCoords
* @param {object} trace
* (optional) full trace object to be added on to output
*
* @return {object} out
* GeoJSON object
*/
exports.makePolygon = function(coords, trace) {
var out = {};

exports.makePolygon = function(coords) {
if(coords.length === 1) {
out = {
return {
type: 'Polygon',
coordinates: coords
};
}
else {
} else {
var _coords = new Array(coords.length);

for(var i = 0; i < coords.length; i++) {
_coords[i] = [coords[i]];
}

out = {
return {
type: 'MultiPolygon',
coordinates: _coords
};
}

if(trace) out.trace = trace;

return out;
};

/**
Expand Down
10 changes: 8 additions & 2 deletions src/plot_api/plot_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -2748,8 +2748,8 @@ Plotly.purge = function purge(gd) {
// makePlotFramework: Create the plot container and axes
// -------------------------------------------------------
function makePlotFramework(gd) {
var gd3 = d3.select(gd),
fullLayout = gd._fullLayout;
var gd3 = d3.select(gd);
var fullLayout = gd._fullLayout;

// Plot container
fullLayout._container = gd3.selectAll('.plot-container').data([0]);
Expand Down Expand Up @@ -2795,9 +2795,15 @@ function makePlotFramework(gd) {
fullLayout._defs = fullLayout._paper.append('defs')
.attr('id', 'defs-' + fullLayout._uid);

fullLayout._clips = fullLayout._defs.append('g')
.classed('clips', true);

fullLayout._topdefs = fullLayout._toppaper.append('defs')
.attr('id', 'topdefs-' + fullLayout._uid);

fullLayout._topclips = fullLayout._topdefs.append('g')
.classed('clips', true);

fullLayout._bgLayer = fullLayout._paper.append('g')
.classed('bglayer', true);

Expand Down
22 changes: 4 additions & 18 deletions src/plot_api/subroutines.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,7 @@ exports.lsInner = function(gd) {
// Clip so that data only shows up on the plot area.
plotinfo.clipId = 'clip' + fullLayout._uid + subplot + 'plot';

var plotClip = fullLayout._defs.selectAll('g.clips')
.selectAll('#' + plotinfo.clipId)
var plotClip = fullLayout._clips.selectAll('#' + plotinfo.clipId)
.data([0]);

plotClip.enter().append('clipPath')
Expand Down Expand Up @@ -490,28 +489,15 @@ exports.doTicksRelayout = function(gd) {

exports.doModeBar = function(gd) {
var fullLayout = gd._fullLayout;
var subplotIds, subplotObj, i;

ModeBar.manage(gd);
initInteractions(gd);

subplotIds = Plots.getSubplotIds(fullLayout, 'gl3d');
for(i = 0; i < subplotIds.length; i++) {
subplotObj = fullLayout[subplotIds[i]]._scene;
subplotObj.updateFx(fullLayout.dragmode, fullLayout.hovermode);
for(var i = 0; i < fullLayout._basePlotModules.length; i++) {
var updateFx = fullLayout._basePlotModules[i].updateFx;
if(updateFx) updateFx(fullLayout);
}

subplotIds = Plots.getSubplotIds(fullLayout, 'gl2d');
for(i = 0; i < subplotIds.length; i++) {
subplotObj = fullLayout._plots[subplotIds[i]]._scene2d;
subplotObj.updateFx(fullLayout.dragmode);
}

subplotIds = Plots.getSubplotIds(fullLayout, 'mapbox');
for(i = 0; i < subplotIds.length; i++) {
subplotObj = fullLayout[subplotIds[i]]._subplot;
subplotObj.updateFx(fullLayout);
}

return Plots.previousPromises(gd);
};
Expand Down
8 changes: 1 addition & 7 deletions src/plots/cartesian/axes.js
Original file line number Diff line number Diff line change
Expand Up @@ -1620,16 +1620,10 @@ axes.makeClipPaths = function(gd) {
}
}

var defGroup = defs.selectAll('g.clips')
.data([0]);

defGroup.enter().append('g')
.classed('clips', true);

// selectors don't work right with camelCase tags,
// have to use class instead
// https://groups.google.com/forum/#!topic/d3-js/6EpAzQ2gU9I
var axClips = defGroup.selectAll('.axesclip')
var axClips = fullLayout._clips.selectAll('.axesclip')
.data(clipList, function(d) { return d.x._id + d.y._id; });

axClips.enter().append('clipPath')
Expand Down
Loading