Skip to content

Commit eab3768

Browse files
committed
Add O(N) hover
1 parent 2b6c58e commit eab3768

File tree

2 files changed

+125
-12
lines changed

2 files changed

+125
-12
lines changed

src/traces/scattergl/index.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -618,15 +618,14 @@ function hoverPoints(pointData, xval, yval, hovermode) {
618618

619619
// pick the id closest to the point
620620
// note that point possibly may not be found
621-
var minDist = maxDistance;
622621
var id, ptx, pty, i, dx, dy, dist, dxy;
623622

624623
if(hovermode === 'x') {
625624
for(i = 0; i < ids.length; i++) {
626625
ptx = x[ids[i]];
627626
dx = Math.abs(xa.c2p(ptx) - xpx);
628-
if(dx < minDist) {
629-
minDist = dx;
627+
if(dx < maxDistance) {
628+
maxDistance = dx;
630629
dy = ya.c2p(y[ids[i]]) - ypx;
631630
dxy = Math.sqrt(dx * dx + dy * dy);
632631
id = ids[i];
@@ -641,8 +640,8 @@ function hoverPoints(pointData, xval, yval, hovermode) {
641640
dy = ya.c2p(pty) - ypx;
642641

643642
dist = Math.sqrt(dx * dx + dy * dy);
644-
if(dist < minDist) {
645-
minDist = dxy = dist;
643+
if(dist < maxDistance) {
644+
maxDistance = dxy = dist;
646645
id = ids[i];
647646
}
648647
}
@@ -726,7 +725,7 @@ function hoverPoints(pointData, xval, yval, hovermode) {
726725
yLabelVal: di.y,
727726

728727
cd: fakeCd,
729-
distance: minDist,
728+
distance: maxDistance,
730729
spikeDistance: dxy
731730
});
732731

src/traces/splom/index.js

Lines changed: 120 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ var calcMarkerSize = require('../scatter/calc').calcMarkerSize;
1717
var calcAxisExpansion = require('../scatter/calc').calcAxisExpansion;
1818
var calcColorscales = require('../scatter/colorscale_calc');
1919
var convertMarkerStyle = require('../scattergl/convert').convertMarkerStyle;
20+
var getTraceColor = require('../scatter/get_trace_color');
2021

2122
var BADNUM = require('../../constants/numerical').BADNUM;
2223
var TOO_MANY_POINTS = require('../scattergl/constants').TOO_MANY_POINTS;
@@ -199,7 +200,6 @@ function plotOne(gd, cd0) {
199200

200201
function hoverPoints(pointData, xval, yval, hovermode) {
201202
var cd = pointData.cd;
202-
var stash = cd[0].t;
203203
var trace = cd[0].trace;
204204
var xa = pointData.xa;
205205
var ya = pointData.ya;
@@ -208,17 +208,131 @@ function hoverPoints(pointData, xval, yval, hovermode) {
208208
var maxDistance = pointData.distance;
209209
var dimensions = trace.dimensions;
210210

211-
var xi, yi;
212-
for(var i = 0; i < dimensions.length; i++) {
211+
var xi, yi, i;
212+
for(i = 0; i < dimensions.length; i++) {
213213
if(trace.xaxes[i] === xa._id) xi = i;
214214
if(trace.yaxes[i] === ya._id) yi = i;
215215
}
216216

217-
var x = dimensions[xi].values;
218-
var y = dimensions[yi].values;
217+
var xData = dimensions[xi].values;
218+
var yData = dimensions[yi].values;
219+
220+
var id, ptx, pty, dx, dy, dist, dxy;
221+
222+
if(hovermode === 'x') {
223+
for(i = 0; i < xData.length; i++) {
224+
ptx = xData[i];
225+
dx = Math.abs(xa.c2p(ptx) - xpx);
226+
if(dx < maxDistance) {
227+
maxDistance = dx;
228+
dy = ya.c2p(yData[i]) - ypx;
229+
dxy = Math.sqrt(dx * dx + dy * dy);
230+
id = i;
231+
}
232+
}
233+
}
234+
else {
235+
for(i = 0; i < xData.length; i++) {
236+
ptx = xData[i];
237+
pty = yData[i];
238+
dx = xa.c2p(ptx) - xpx;
239+
dy = ya.c2p(pty) - ypx;
240+
241+
dist = Math.sqrt(dx * dx + dy * dy);
242+
if(dist < maxDistance) {
243+
maxDistance = dxy = dist;
244+
id = i;
245+
}
246+
}
247+
}
248+
249+
pointData.index = id;
250+
251+
252+
if(id === undefined) return [pointData];
253+
254+
// the closest data point
255+
var di = {
256+
pointNumber: id,
257+
x: xData[id],
258+
y: yData[id]
259+
};
260+
261+
262+
// that is single-item arrays_to_calcdata excerpt, since we are doing it for a single point and we don't have to do it beforehead for 1e6 points
263+
// FIXME: combine with scattergl hover di calc
264+
di.tx = Array.isArray(trace.text) ? trace.text[id] : trace.text;
265+
di.htx = Array.isArray(trace.hovertext) ? trace.hovertext[id] : trace.hovertext;
266+
di.data = Array.isArray(trace.customdata) ? trace.customdata[id] : trace.customdata;
267+
di.tp = Array.isArray(trace.textposition) ? trace.textposition[id] : trace.textposition;
268+
269+
var font = trace.textfont;
270+
if(font) {
271+
di.ts = Array.isArray(font.size) ? font.size[id] : font.size;
272+
di.tc = Array.isArray(font.color) ? font.color[id] : font.color;
273+
di.tf = Array.isArray(font.family) ? font.family[id] : font.family;
274+
}
275+
276+
var marker = trace.marker;
277+
if(marker) {
278+
di.ms = Lib.isArrayOrTypedArray(marker.size) ? marker.size[id] : marker.size;
279+
di.mo = Lib.isArrayOrTypedArray(marker.opacity) ? marker.opacity[id] : marker.opacity;
280+
di.mx = Array.isArray(marker.symbol) ? marker.symbol[id] : marker.symbol;
281+
di.mc = Lib.isArrayOrTypedArray(marker.color) ? marker.color[id] : marker.color;
282+
}
283+
284+
var line = marker && marker.line;
285+
if(line) {
286+
di.mlc = Array.isArray(line.color) ? line.color[id] : line.color;
287+
di.mlw = Lib.isArrayOrTypedArray(line.width) ? line.width[id] : line.width;
288+
}
289+
290+
var grad = marker && marker.gradient;
291+
if(grad && grad.type !== 'none') {
292+
di.mgt = Array.isArray(grad.type) ? grad.type[id] : grad.type;
293+
di.mgc = Array.isArray(grad.color) ? grad.color[id] : grad.color;
294+
}
295+
296+
var xp = xa.c2p(di.x, true);
297+
var yp = ya.c2p(di.y, true);
298+
var rad = di.mrc || 1;
299+
300+
var hoverlabel = trace.hoverlabel;
301+
302+
if(hoverlabel) {
303+
di.hbg = Array.isArray(hoverlabel.bgcolor) ? hoverlabel.bgcolor[id] : hoverlabel.bgcolor;
304+
di.hbc = Array.isArray(hoverlabel.bordercolor) ? hoverlabel.bordercolor[id] : hoverlabel.bordercolor;
305+
di.hts = Array.isArray(hoverlabel.font.size) ? hoverlabel.font.size[id] : hoverlabel.font.size;
306+
di.htc = Array.isArray(hoverlabel.font.color) ? hoverlabel.font.color[id] : hoverlabel.font.color;
307+
di.htf = Array.isArray(hoverlabel.font.family) ? hoverlabel.font.family[id] : hoverlabel.font.family;
308+
di.hnl = Array.isArray(hoverlabel.namelength) ? hoverlabel.namelength[id] : hoverlabel.namelength;
309+
}
310+
var hoverinfo = trace.hoverinfo;
311+
if(hoverinfo) {
312+
di.hi = Array.isArray(hoverinfo) ? hoverinfo[id] : hoverinfo;
313+
}
314+
315+
316+
var fakeCd = {};
317+
fakeCd[pointData.index] = di;
318+
319+
Lib.extendFlat(pointData, {
320+
color: getTraceColor(trace, di),
321+
322+
x0: xp - rad,
323+
x1: xp + rad,
324+
xLabelVal: di.x,
325+
326+
y0: yp - rad,
327+
y1: yp + rad,
328+
yLabelVal: di.y,
219329

330+
cd: fakeCd,
331+
distance: maxDistance,
332+
spikeDistance: dxy
333+
});
220334

221-
console.log(x, y);
335+
return [pointData];
222336
}
223337

224338
function selectPoints(searchInfo, polygon) {

0 commit comments

Comments
 (0)