Skip to content

Commit de42330

Browse files
committed
fix scattermapbox hover & selection for 180 < lon < 360
1 parent 8443d63 commit de42330

File tree

3 files changed

+51
-34
lines changed

3 files changed

+51
-34
lines changed

src/traces/scattermapbox/hover.js

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,32 +10,40 @@
1010
'use strict';
1111

1212
var Fx = require('../../components/fx');
13+
var Lib = require('../../lib');
1314
var getTraceColor = require('../scatter/get_trace_color');
1415
var fillHoverText = require('../scatter/fill_hover_text');
1516
var BADNUM = require('../../constants/numerical').BADNUM;
1617

1718
module.exports = function hoverPoints(pointData, xval, yval) {
18-
var cd = pointData.cd,
19-
trace = cd[0].trace,
20-
xa = pointData.xa,
21-
ya = pointData.ya;
19+
var cd = pointData.cd;
20+
var trace = cd[0].trace;
21+
var xa = pointData.xa;
22+
var ya = pointData.ya;
23+
var subplot = pointData.subplot;
2224

2325
// compute winding number about [-180, 180] globe
2426
var winding = (xval >= 0) ?
25-
Math.floor((xval + 180) / 360) :
26-
Math.ceil((xval - 180) / 360);
27+
Math.floor((xval + 180) / 360) :
28+
Math.ceil((xval - 180) / 360);
2729

2830
// shift longitude to [-180, 180] to determine closest point
2931
var lonShift = winding * 360;
3032
var xval2 = xval - lonShift;
3133

34+
function wrapLon(lon) {
35+
return Lib.wrap180(lon);
36+
}
37+
3238
function distFn(d) {
3339
var lonlat = d.lonlat;
34-
3540
if(lonlat[0] === BADNUM) return Infinity;
3641

37-
var dx = Math.abs(xa.c2p(lonlat) - xa.c2p([xval2, lonlat[1]]));
38-
var dy = Math.abs(ya.c2p(lonlat) - ya.c2p([lonlat[0], yval]));
42+
var lon = wrapLon(lonlat[0]);
43+
var lat = lonlat[1];
44+
var pt = subplot.project([lon, lat]);
45+
var dx = pt.x - xa.c2p([xval2, lat]);
46+
var dy = pt.y - ya.c2p([lon, yval]);
3947
var rad = Math.max(3, d.mrc || 0);
4048

4149
return Math.max(Math.sqrt(dx * dx + dy * dy) - rad, 1 - 3 / rad);
@@ -46,14 +54,14 @@ module.exports = function hoverPoints(pointData, xval, yval) {
4654
// skip the rest (for this trace) if we didn't find a close point
4755
if(pointData.index === false) return;
4856

49-
var di = cd[pointData.index],
50-
lonlat = di.lonlat,
51-
lonlatShifted = [lonlat[0] + lonShift, lonlat[1]];
57+
var di = cd[pointData.index];
58+
var lonlat = di.lonlat;
59+
var lonlatShifted = [wrapLon(lonlat[0]) + lonShift, lonlat[1]];
5260

5361
// shift labels back to original winded globe
54-
var xc = xa.c2p(lonlatShifted),
55-
yc = ya.c2p(lonlatShifted),
56-
rad = di.mrc || 1;
62+
var xc = xa.c2p(lonlatShifted);
63+
var yc = ya.c2p(lonlatShifted);
64+
var rad = di.mrc || 1;
5765

5866
pointData.x0 = xc - rad;
5967
pointData.x1 = xc + rad;
@@ -72,7 +80,6 @@ function getExtraText(trace, di, labels) {
7280
var isAll = parts.indexOf('all') !== -1;
7381
var hasLon = parts.indexOf('lon') !== -1;
7482
var hasLat = parts.indexOf('lat') !== -1;
75-
7683
var lonlat = di.lonlat;
7784
var text = [];
7885

src/traces/scattermapbox/select.js

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88

9-
109
'use strict';
1110

11+
var Lib = require('../../lib');
1212
var subtypes = require('../scatter/subtypes');
1313

1414
module.exports = function selectPoints(searchInfo, polygon) {
@@ -17,8 +17,7 @@ module.exports = function selectPoints(searchInfo, polygon) {
1717
var ya = searchInfo.yaxis;
1818
var selection = [];
1919
var trace = cd[0].trace;
20-
21-
var di, lonlat, x, y, i;
20+
var i;
2221

2322
if(!subtypes.hasMarkers(trace)) return [];
2423

@@ -28,12 +27,12 @@ module.exports = function selectPoints(searchInfo, polygon) {
2827
}
2928
} else {
3029
for(i = 0; i < cd.length; i++) {
31-
di = cd[i];
32-
lonlat = di.lonlat;
33-
x = xa.c2p(lonlat);
34-
y = ya.c2p(lonlat);
30+
var di = cd[i];
31+
var lonlat = di.lonlat;
32+
var lonlat2 = [Lib.wrap180(lonlat[0]), lonlat[1]];
33+
var xy = [xa.c2p(lonlat2), ya.c2p(lonlat2)];
3534

36-
if(polygon.contains([x, y])) {
35+
if(polygon.contains(xy)) {
3736
selection.push({
3837
pointNumber: i,
3938
lon: lonlat[0],

test/jasmine/tests/scattermapbox_test.js

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -417,10 +417,7 @@ describe('scattermapbox convert', function() {
417417
});
418418

419419
describe('@noCI scattermapbox hover', function() {
420-
'use strict';
421-
422420
var hoverPoints = ScatterMapbox.hoverPoints;
423-
424421
var gd;
425422

426423
beforeAll(function(done) {
@@ -432,9 +429,9 @@ describe('@noCI scattermapbox hover', function() {
432429

433430
var data = [{
434431
type: 'scattermapbox',
435-
lon: [10, 20, 30],
436-
lat: [10, 20, 30],
437-
text: ['A', 'B', 'C']
432+
lon: [10, 20, 30, 300],
433+
lat: [10, 20, 30, 10],
434+
text: ['A', 'B', 'C', 'D']
438435
}];
439436

440437
Plotly.plot(gd, data, { autosize: true }).then(done);
@@ -446,16 +443,17 @@ describe('@noCI scattermapbox hover', function() {
446443
});
447444

448445
function getPointData(gd) {
449-
var cd = gd.calcdata,
450-
mapbox = gd._fullLayout.mapbox._subplot;
446+
var cd = gd.calcdata;
447+
var subplot = gd._fullLayout.mapbox._subplot;
451448

452449
return {
453450
index: false,
454451
distance: 20,
455452
cd: cd[0],
456453
trace: cd[0][0].trace,
457-
xa: mapbox.xaxis,
458-
ya: mapbox.yaxis
454+
subplot: subplot,
455+
xa: subplot.xaxis,
456+
ya: subplot.yaxis
459457
};
460458
}
461459

@@ -473,6 +471,19 @@ describe('@noCI scattermapbox hover', function() {
473471
expect(out.color).toEqual('#1f77b4');
474472
});
475473

474+
it('should generate hover label info (lon > 180 case)', function() {
475+
var xval = 301;
476+
var yval = 11;
477+
var out = hoverPoints(getPointData(gd), xval, yval)[0];
478+
479+
expect(out.index).toEqual(3);
480+
expect([out.x0, out.x1, out.y0, out.y1]).toBeCloseToArray([
481+
1122.33, 1124.33, 105.41, 107.41
482+
]);
483+
expect(out.extraText).toEqual('(300°, 10°)<br>D');
484+
expect(out.color).toEqual('#1f77b4');
485+
});
486+
476487
it('should skip over blank and non-string text items', function(done) {
477488
var xval = 11,
478489
yval = 11,

0 commit comments

Comments
 (0)