Skip to content

Commit e5875a9

Browse files
committed
fix tests related to new spike mode
1 parent b14286b commit e5875a9

File tree

3 files changed

+105
-54
lines changed

3 files changed

+105
-54
lines changed

src/components/fx/hover.js

Lines changed: 100 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ var Registry = require('../../registry');
2424

2525
var helpers = require('./helpers');
2626
var constants = require('./constants');
27+
var getTraceColor = require('../../traces/scatter/get_trace_color');
2728

2829
// hover labels for multiple horizontal bars get tilted by some angle,
2930
// then need to be offset differently if they overlap
@@ -234,8 +235,8 @@ function _hover(gd, evt, subplot, noHoverEvent) {
234235
pointData,
235236
closedataPreviousLength,
236237

237-
// closestPoints: the set of candidate points we've found to draw spikes to
238-
closestPoints = {
238+
// spikePoints: the set of candidate points we've found to draw spikes to
239+
spikePoints = {
239240
hLinePoint: null,
240241
vLinePoint: null
241242
};
@@ -331,8 +332,8 @@ function _hover(gd, evt, subplot, noHoverEvent) {
331332
// within one trace mode can sometimes be overridden
332333
mode = hovermode;
333334

334-
var hoverdistance = fullLayout.hoverdistance ? fullLayout.hoverdistance === -1 ? Infinity : fullLayout.hoverdistance : constants.MAXDIST;
335-
var spikedistance = fullLayout.spikedistance ? fullLayout.spikedistance === -1 ? Infinity : fullLayout.spikedistance : hoverdistance;
335+
var hoverdistance = fullLayout.hoverdistance ? fullLayout.hoverdistance === 0 ? Infinity : fullLayout.hoverdistance : constants.MAXDIST;
336+
var spikedistance = fullLayout.spikedistance ? fullLayout.spikedistance === 0 ? Infinity : fullLayout.spikedistance : hoverdistance;
336337

337338
// container for new point, also used to pass info into module.hoverPoints
338339
pointData = {
@@ -391,11 +392,11 @@ function _hover(gd, evt, subplot, noHoverEvent) {
391392
// Find the points for the spikes first to avoid overwriting the hoverLabels data.
392393
if(fullLayout._has('cartesian')) {
393394
if(fullLayout.hovermode === 'closest') {
394-
closestPoints.hLinePoint = findClosestPoint(pointData, xval, yval, 'closest', closestPoints.hLinePoint, spikedistance);
395-
closestPoints.vLinePoint = findClosestPoint(pointData, xval, yval, 'closest', closestPoints.vLinePoint, spikedistance);
395+
spikePoints.hLinePoint = setClosestPoint(pointData, xval, yval, 'closest', spikePoints.hLinePoint, spikedistance, 'h');
396+
spikePoints.vLinePoint = setClosestPoint(pointData, xval, yval, 'closest', spikePoints.vLinePoint, spikedistance, 'v');
396397
} else {
397-
closestPoints.hLinePoint = findClosestPoint(pointData, xval, yval, 'y', closestPoints.hLinePoint, spikedistance);
398-
closestPoints.vLinePoint = findClosestPoint(pointData, xval, yval, 'x', closestPoints.vLinePoint, spikedistance);
398+
spikePoints.hLinePoint = setClosestPoint(pointData, xval, yval, 'y', spikePoints.hLinePoint, spikedistance, 'h');
399+
spikePoints.vLinePoint = setClosestPoint(pointData, xval, yval, 'x', spikePoints.vLinePoint, spikedistance, 'v');
399400
}
400401
}
401402

@@ -424,21 +425,72 @@ function _hover(gd, evt, subplot, noHoverEvent) {
424425
}
425426
}
426427

427-
function findClosestPoint(pointData, xval, yval, mode, endPoint, spikedistance) {
428+
function findClosestPoints(pointData, xval, yval, hovermode) {
429+
var cd = pointData.cd,
430+
trace = cd[0].trace,
431+
xa = pointData.xa,
432+
ya = pointData.ya,
433+
xpx = xa.c2p(xval),
434+
ypx = ya.c2p(yval),
435+
hoveron = trace.hoveron || '';
436+
437+
if(hoveron.indexOf('points') !== -1) {
438+
var dx = function(di) {
439+
// scatter points: d.mrc is the calculated marker radius
440+
// adjust the distance so if you're inside the marker it
441+
// always will show up regardless of point size, but
442+
// prioritize smaller points
443+
var rad = Math.max(3, di.mrc || 0);
444+
return Math.max(Math.abs(xa.c2p(di.x) - xpx) - rad, 1 - 3 / rad);
445+
},
446+
dy = function(di) {
447+
var rad = Math.max(3, di.mrc || 0);
448+
return Math.max(Math.abs(ya.c2p(di.y) - ypx) - rad, 1 - 3 / rad);
449+
},
450+
dxy = function(di) {
451+
var rad = Math.max(3, di.mrc || 0),
452+
dx = xa.c2p(di.x) - xpx,
453+
dy = ya.c2p(di.y) - ypx;
454+
return Math.max(Math.sqrt(dx * dx + dy * dy) - rad, 1 - 3 / rad);
455+
},
456+
distfn = helpers.getDistanceFunction(hovermode, dx, dy, dxy);
457+
458+
helpers.getClosest(cd, distfn, pointData);
459+
460+
// skip the rest (for this trace) if we didn't find a close point
461+
if(pointData.index !== false) {
462+
463+
// the closest data point
464+
var di = cd[pointData.index],
465+
xc = xa.c2p(di.x, true),
466+
yc = ya.c2p(di.y, true),
467+
rad = di.mrc || 1;
468+
469+
Lib.extendFlat(pointData, {
470+
color: getTraceColor(trace, di),
471+
x0: xc - rad,
472+
x1: xc + rad,
473+
y0: yc - rad,
474+
y1: yc + rad,
475+
});
476+
return [pointData];
477+
}
478+
}
479+
}
480+
481+
function setClosestPoint(pointData, xval, yval, mode, endPoint, spikedistance, type) {
428482
var tmpDistance = pointData.distance;
429483
var tmpIndex = pointData.index;
430484
var resultPoint = endPoint;
431485
pointData.distance = spikedistance;
432486
pointData.index = false;
433-
var closestPoints = trace._module.hoverPoints(pointData, xval, yval, mode);
487+
var closestPoints = findClosestPoints(pointData, xval, yval, mode);
434488
if(closestPoints) {
435489
closestPoints = closestPoints.filter(function(point) {
436-
if(mode === 'x') {
490+
if(type === 'v') {
437491
return point.xa.showspikes;
438-
} else if(mode === 'y') {
492+
} else if(type === 'h') {
439493
return point.ya.showspikes;
440-
} else if(mode === 'closest') {
441-
return point.ya.showspikes && point.ya.showspikes;
442494
}
443495
});
444496
if(closestPoints.length) {
@@ -477,24 +529,24 @@ function _hover(gd, evt, subplot, noHoverEvent) {
477529
};
478530
var oldspikepoints = gd._spikepoints,
479531
newspikepoints = {
480-
vLinePoint: closestPoints.vLinePoint,
481-
hLinePoint: closestPoints.hLinePoint
532+
vLinePoint: spikePoints.vLinePoint,
533+
hLinePoint: spikePoints.hLinePoint
482534
};
483535
gd._spikepoints = newspikepoints;
484536

485537
if(hoverData.length === 0) {
486538
var result = dragElement.unhoverRaw(gd, evt);
487-
if(fullLayout._has('cartesian') && ((closestPoints.hLinePoint !== null) || (closestPoints.vLinePoint !== null))) {
539+
if(fullLayout._has('cartesian') && ((spikePoints.hLinePoint !== null) || (spikePoints.vLinePoint !== null))) {
488540
if(spikesChanged(oldspikepoints)) {
489-
createSpikelines2(closestPoints, spikelineOpts);
541+
createSpikelines(spikePoints, spikelineOpts);
490542
}
491543
}
492544
return result;
493545
}
494546

495547
if(fullLayout._has('cartesian')) {
496548
if(spikesChanged(oldspikepoints)) {
497-
createSpikelines2(closestPoints, spikelineOpts);
549+
createSpikelines(spikePoints, spikelineOpts);
498550
}
499551
}
500552

@@ -1170,17 +1222,13 @@ function cleanPoint(d, hovermode) {
11701222
return d;
11711223
}
11721224

1173-
function createSpikelines2(closestPoints, opts) {
1225+
function createSpikelines(closestPoints, opts) {
11741226
var hovermode = opts.hovermode;
11751227
var container = opts.container;
11761228
var fullLayout = opts.fullLayout;
11771229
var evt = opts.event;
1178-
var hLinePoint,
1179-
vLinePoint,
1180-
xa,
1181-
ya,
1182-
hLinePointY,
1183-
vLinePointX;
1230+
var xa,
1231+
ya;
11841232

11851233
var showY = closestPoints.hLinePoint ? true : false;
11861234
var showX = closestPoints.vLinePoint ? true : false;
@@ -1190,31 +1238,22 @@ function createSpikelines2(closestPoints, opts) {
11901238

11911239
if(!(showX || showY)) return;
11921240

1241+
var contrastColor = Color.combine(fullLayout.plot_bgcolor, fullLayout.paper_bgcolor);
1242+
1243+
// Horizontal line (to y-axis)
11931244
if(showY) {
1194-
hLinePoint = closestPoints.hLinePoint;
1245+
var hLinePoint = closestPoints.hLinePoint;
1246+
xa = hLinePoint && hLinePoint.xa;
11951247
ya = hLinePoint && hLinePoint.ya;
1196-
var ySnap = ya.spikesnap;
1248+
var ySnap = ya.spikesnap,
1249+
hLinePointX,
1250+
hLinePointY;
11971251
if(ySnap === 'cursor') {
11981252
hLinePointY = evt.offsetY;
11991253
} else {
12001254
hLinePointY = ya._offset + (hLinePoint.y0 + hLinePoint.y1) / 2;
12011255
}
1202-
}
1203-
if(showX) {
1204-
vLinePoint = closestPoints.vLinePoint;
1205-
xa = vLinePoint && vLinePoint.xa;
1206-
var xSnap = xa.spikesnap;
1207-
if(xSnap === 'cursor') {
1208-
vLinePointX = evt.offsetX;
1209-
} else {
1210-
vLinePointX = xa._offset + (vLinePoint.x0 + vLinePoint.x1) / 2;
1211-
}
1212-
}
1213-
1214-
var contrastColor = Color.combine(fullLayout.plot_bgcolor, fullLayout.paper_bgcolor);
1215-
1216-
// Horizontal line (to y-axis)
1217-
if(showY) {
1256+
hLinePointX = xa._offset + (hLinePoint.x0 + hLinePoint.x1) / 2;
12181257
var dfltHLineColor = tinycolor.readability(hLinePoint.color, contrastColor) < 1.5 ?
12191258
Color.contrast(contrastColor) : hLinePoint.color;
12201259
var yMode = ya.spikemode;
@@ -1224,14 +1263,14 @@ function createSpikelines2(closestPoints, opts) {
12241263
var yThickness = ya.spikethickness;
12251264
var yColor = ya.spikecolor || dfltHLineColor;
12261265
var yBB = ya._boundingBox;
1227-
var xEdge = ((yBB.left + yBB.right) / 2) < vLinePointX ? yBB.right : yBB.left;
1266+
var xEdge = ((yBB.left + yBB.right) / 2) < hLinePointX ? yBB.right : yBB.left;
12281267
var xBase;
12291268
var xEndSpike;
12301269

12311270
if(yMode.indexOf('toaxis') !== -1 || yMode.indexOf('across') !== -1) {
12321271
if(yMode.indexOf('toaxis') !== -1) {
12331272
xBase = xEdge;
1234-
xEndSpike = vLinePointX;
1273+
xEndSpike = hLinePointX;
12351274
}
12361275
if(yMode.indexOf('across') !== -1) {
12371276
xBase = ya._counterSpan[0];
@@ -1279,24 +1318,36 @@ function createSpikelines2(closestPoints, opts) {
12791318
}
12801319

12811320
if(showX) {
1321+
var vLinePoint = closestPoints.vLinePoint;
1322+
xa = vLinePoint && vLinePoint.xa;
1323+
ya = vLinePoint && vLinePoint.ya;
1324+
var xSnap = xa.spikesnap,
1325+
vLinePointX,
1326+
vLinePointY;
1327+
if(xSnap === 'cursor') {
1328+
vLinePointX = evt.offsetX;
1329+
} else {
1330+
vLinePointX = xa._offset + (vLinePoint.x0 + vLinePoint.x1) / 2;
1331+
}
1332+
vLinePointY = ya._offset + (vLinePoint.y0 + vLinePoint.y1) / 2;
12821333
var dfltVLineColor = tinycolor.readability(vLinePoint.color, contrastColor) < 1.5 ?
1283-
Color.contrast(contrastColor) : vLinePoint.color;
1334+
Color.contrast(contrastColor) : vLinePoint.color;
12841335
var xMode = xa.spikemode;
12851336
if(hovermode !== 'closest' && xMode.indexOf('toaxis') !== -1) {
12861337
xMode = xMode.replace('toaxis', 'across');
12871338
}
12881339
var xThickness = xa.spikethickness;
12891340
var xColor = xa.spikecolor || dfltVLineColor;
12901341
var xBB = xa._boundingBox;
1291-
var yEdge = ((xBB.top + xBB.bottom) / 2) < hLinePointY ? xBB.bottom : xBB.top;
1342+
var yEdge = ((xBB.top + xBB.bottom) / 2) < vLinePointY ? xBB.bottom : xBB.top;
12921343

12931344
var yBase;
12941345
var yEndSpike;
12951346

12961347
if(xMode.indexOf('toaxis') !== -1 || xMode.indexOf('across') !== -1) {
12971348
if(xMode.indexOf('toaxis') !== -1) {
12981349
yBase = yEdge;
1299-
yEndSpike = hLinePointY;
1350+
yEndSpike = vLinePointY;
13001351
}
13011352
if(xMode.indexOf('across') !== -1) {
13021353
yBase = xa._counterSpan[0];

src/components/fx/layout_attributes.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ module.exports = {
4646
editType: 'none',
4747
description: [
4848
'Sets the default distance (in points) to look for data',
49-
'to add hover labels'
49+
'to add hover labels (zero means no cutoff)'
5050
].join(' ')
5151
},
5252
spikedistance: {
@@ -56,8 +56,8 @@ module.exports = {
5656
role: 'style',
5757
editType: 'none',
5858
description: [
59-
'Sets the default distance (in points) to look for data',
60-
'to draw spikelines to. By default inherits from hoverdistance'
59+
'Sets the default distance (in points) to look for data to draw',
60+
'spikelines to (zero means no cutoff). By default inherits from hoverdistance'
6161
].join(' ')
6262
},
6363
hoverlabel: {

test/jasmine/tests/hover_spikeline_test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ describe('spikeline', function() {
6565
Plotly.plot(gd, _mock).then(function() {
6666
_hover({xval: 2, yval: 3}, 'xy');
6767
_assert(
68-
[[80, 250, 557, 250], [80, 250, 557, 250], [557, 401, 557, 250], [557, 401, 557, 250]],
68+
[[557, 401, 557, 250], [557, 401, 557, 250], [80, 250, 557, 250], [80, 250, 557, 250]],
6969
[[83, 250]]
7070
);
7171
})
@@ -90,7 +90,7 @@ describe('spikeline', function() {
9090
Plotly.plot(gd, _mock).then(function() {
9191
_hover({xval: 2, yval: 3}, 'xy');
9292
_assert(
93-
[[80, 250, 557, 250], [80, 250, 557, 250], [557, 401, 557, 250], [557, 401, 557, 250]],
93+
[[557, 401, 557, 250], [557, 401, 557, 250], [80, 250, 557, 250], [80, 250, 557, 250]],
9494
[[83, 250]]
9595
);
9696
})

0 commit comments

Comments
 (0)