Skip to content

Commit 8076f93

Browse files
committed
Add quiver jasmine and image tests
1 parent e07d950 commit 8076f93

15 files changed

+858
-62
lines changed

src/traces/quiver/defaults.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
1717
var y = coerce('y');
1818
var u = coerce('u');
1919
var v = coerce('v');
20+
21+
// Optional scalar field for colorscale
22+
coerce('c');
2023

2124
// Simple validation - check if we have the required arrays
2225
if(!x || !Array.isArray(x) || x.length === 0 ||

src/traces/quiver/event_data.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
module.exports = function eventData(out, pt, trace, cd, pointNumber) {
44
out.x = pt.x;
55
out.y = pt.y;
6-
out.u = trace.u[pointNumber];
7-
out.v = trace.v[pointNumber];
8-
out.pointNumber = pointNumber;
9-
out.trace = trace;
6+
out.u = trace.u ? trace.u[pointNumber] : undefined;
7+
out.v = trace.v ? trace.v[pointNumber] : undefined;
8+
9+
return out;
1010
};
1111

1212

src/traces/quiver/format_labels.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
'use strict';
2+
3+
var Axes = require('../../plots/cartesian/axes');
4+
5+
module.exports = function formatLabels(cdi, trace, fullLayout) {
6+
var labels = {};
7+
8+
var xa = Axes.getFromId({ _fullLayout: fullLayout }, trace.xaxis || 'x');
9+
var ya = Axes.getFromId({ _fullLayout: fullLayout }, trace.yaxis || 'y');
10+
11+
var x = cdi.x;
12+
var y = cdi.y;
13+
14+
labels.xLabel = Axes.tickText(xa, xa.c2l(x), true).text;
15+
labels.yLabel = Axes.tickText(ya, ya.c2l(y), true).text;
16+
17+
var u = trace.u ? trace.u[cdi.i] : 0;
18+
var v = trace.v ? trace.v[cdi.i] : 0;
19+
20+
// Format u and v as plain numbers
21+
labels.uLabel = String(u);
22+
labels.vLabel = String(v);
23+
24+
return labels;
25+
};
26+

src/traces/quiver/hover.js

Lines changed: 47 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
var Lib = require('../../lib');
44
var Fx = require('../../components/fx');
5-
var Registry = require('../../registry');
5+
var getTraceColor = require('../scatter/get_trace_color');
66

77
module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
88
var cd = pointData.cd;
@@ -12,66 +12,55 @@ module.exports = function hoverPoints(pointData, xval, yval, hovermode) {
1212
var xpx = xa.c2p(xval);
1313
var ypx = ya.c2p(yval);
1414

15-
// Find the closest arrow base point to the hover point
16-
var minDistance = Infinity;
17-
var closestPoint = null;
18-
var closestIndex = -1;
19-
20-
// Each cd[i] is a calcdata point object with x/y
21-
for(var i = 0; i < cd.length; i++) {
22-
var cdi = cd[i];
23-
if(cdi.x === undefined || cdi.y === undefined) continue;
24-
25-
var px = xa.c2p(cdi.x);
26-
var py = ya.c2p(cdi.y);
27-
28-
var distance = Math.sqrt((xpx - px) * (xpx - px) + (ypx - py) * (ypx - py));
29-
30-
if(distance < minDistance) {
31-
minDistance = distance;
32-
closestPoint = cdi;
33-
closestIndex = i;
34-
}
35-
}
36-
37-
var maxHoverDist = pointData.distance === Infinity ? Infinity : (trace.hoverdistance || 20);
38-
if(!closestPoint || minDistance > maxHoverDist) return;
39-
40-
// Create hover point data with proper label values and spikeline support
41-
var hoverPoint = {
42-
x: closestPoint.x,
43-
y: closestPoint.y,
44-
u: trace.u ? trace.u[closestIndex] : undefined,
45-
v: trace.v ? trace.v[closestIndex] : undefined,
46-
text: Array.isArray(trace.text) ? trace.text[closestIndex] : trace.text,
47-
name: trace.name || '',
48-
trace: trace,
49-
index: closestIndex,
50-
// Label values for formatting
51-
xLabelVal: closestPoint.x,
52-
yLabelVal: closestPoint.y,
53-
uLabelVal: trace.u ? trace.u[closestIndex] : undefined,
54-
vLabelVal: trace.v ? trace.v[closestIndex] : undefined,
55-
// Spikeline support
56-
xa: pointData.xa,
57-
ya: pointData.ya,
58-
x0: closestPoint.x,
59-
x1: closestPoint.x,
60-
y0: closestPoint.y,
61-
y1: closestPoint.y,
62-
distance: minDistance,
63-
spikeDistance: minDistance,
64-
curveNumber: trace.index,
65-
color: trace.line ? trace.line.color : 'blue'
15+
var distfn = function(di) {
16+
var x = xa.c2p(di.x) - xpx;
17+
var y = ya.c2p(di.y) - ypx;
18+
return Math.max(Math.sqrt(x * x + y * y), 1 - 3 / Math.max(3, di.mrc || 0));
6619
};
6720

68-
// Set hover text
69-
var hovertext = trace.hovertext || trace.text;
70-
if(hovertext && hovertext[closestIndex]) {
71-
hoverPoint.hovertext = hovertext[closestIndex];
72-
}
21+
Fx.getClosest(cd, distfn, pointData);
7322

74-
return [hoverPoint];
23+
// skip if we didn't find a close point
24+
if(pointData.index === false) return;
25+
26+
// the closest data point
27+
var di = cd[pointData.index];
28+
var xc = xa.c2p(di.x, true);
29+
var yc = ya.c2p(di.y, true);
30+
31+
// now we're done using the whole `calcdata` array, replace the
32+
// index with the original index
33+
pointData.index = di.i;
34+
35+
var u = trace.u ? trace.u[di.i] : 0;
36+
var v = trace.v ? trace.v[di.i] : 0;
37+
38+
// Build extraText to show u and v values
39+
var extraText = 'u: ' + u + ', v: ' + v;
40+
41+
Lib.extendFlat(pointData, {
42+
color: getTraceColor(trace, di),
43+
44+
x0: xc - 3,
45+
x1: xc + 3,
46+
xLabelVal: di.x,
47+
48+
y0: yc - 3,
49+
y1: yc + 3,
50+
yLabelVal: di.y,
51+
52+
uLabelVal: u,
53+
vLabelVal: v,
54+
55+
extraText: extraText,
56+
57+
spikeDistance: Math.sqrt((xpx - xc) * (xpx - xc) + (ypx - yc) * (ypx - yc)),
58+
hovertemplate: trace.hovertemplate
59+
});
60+
61+
Lib.fillText(di, trace, pointData);
62+
63+
return [pointData];
7564
};
7665

7766

src/traces/quiver/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ module.exports = {
1515
style: require('./style'),
1616
styleOnSelect: require('../scatter/style').styleOnSelect,
1717
hoverPoints: require('./hover'),
18+
formatLabels: require('./format_labels'),
1819
eventData: require('./event_data'),
1920
selectPoints: require('./select_points'),
2021
animatable: true,
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
{
2+
"data": [
3+
{
4+
"type": "quiver",
5+
"name": "tail anchor",
6+
"x": [1, 1, 1],
7+
"y": [0, 0, 0],
8+
"u": [1, 0, -1],
9+
"v": [1, 1, 1],
10+
"sizemode": "scaled",
11+
"sizeref": 0.5,
12+
"anchor": "tail",
13+
"line": {
14+
"color": "red",
15+
"width": 2
16+
},
17+
"showscale": false,
18+
"xaxis": "x",
19+
"yaxis": "y"
20+
},
21+
{
22+
"type": "quiver",
23+
"name": "tip anchor",
24+
"x": [1, 1, 1],
25+
"y": [1, 1, 1],
26+
"u": [1, 0, -1],
27+
"v": [1, 1, 1],
28+
"sizemode": "scaled",
29+
"sizeref": 0.5,
30+
"anchor": "tip",
31+
"line": {
32+
"color": "blue",
33+
"width": 2
34+
},
35+
"showscale": false,
36+
"xaxis": "x2",
37+
"yaxis": "y2"
38+
},
39+
{
40+
"type": "quiver",
41+
"name": "center anchor",
42+
"x": [1, 1, 1],
43+
"y": [2, 2, 2],
44+
"u": [1, 0, -1],
45+
"v": [1, 1, 1],
46+
"sizemode": "scaled",
47+
"sizeref": 0.5,
48+
"anchor": "center",
49+
"line": {
50+
"color": "green",
51+
"width": 2
52+
},
53+
"showscale": false,
54+
"xaxis": "x3",
55+
"yaxis": "y3"
56+
}
57+
],
58+
"layout": {
59+
"width": 900,
60+
"height": 400,
61+
"showlegend": true,
62+
"xaxis": {
63+
"domain": [0, 0.3],
64+
"range": [-0.5, 2.5],
65+
"title": {"text": "tail anchor"}
66+
},
67+
"yaxis": {
68+
"domain": [0, 1],
69+
"range": [-0.5, 1.5]
70+
},
71+
"xaxis2": {
72+
"domain": [0.35, 0.65],
73+
"range": [-0.5, 2.5],
74+
"title": {"text": "tip anchor"}
75+
},
76+
"yaxis2": {
77+
"domain": [0, 1],
78+
"anchor": "x2",
79+
"range": [0, 2]
80+
},
81+
"xaxis3": {
82+
"domain": [0.7, 1],
83+
"range": [-0.5, 2.5],
84+
"title": {"text": "center anchor"}
85+
},
86+
"yaxis3": {
87+
"domain": [0, 1],
88+
"anchor": "x3",
89+
"range": [1, 3]
90+
}
91+
}
92+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
{
2+
"data": [
3+
{
4+
"type": "quiver",
5+
"name": "small arrows",
6+
"x": [0, 1, 2],
7+
"y": [0, 0, 0],
8+
"u": [1, 1, 1],
9+
"v": [1, 1, 1],
10+
"sizemode": "scaled",
11+
"sizeref": 0.5,
12+
"arrowsize": 0.5,
13+
"anchor": "tail",
14+
"line": {
15+
"color": "red",
16+
"width": 1
17+
},
18+
"showscale": false
19+
},
20+
{
21+
"type": "quiver",
22+
"name": "medium arrows",
23+
"x": [0, 1, 2],
24+
"y": [1, 1, 1],
25+
"u": [1, 1, 1],
26+
"v": [1, 1, 1],
27+
"sizemode": "scaled",
28+
"sizeref": 0.5,
29+
"arrowsize": 1.0,
30+
"anchor": "tail",
31+
"line": {
32+
"color": "blue",
33+
"width": 2
34+
},
35+
"showscale": false
36+
},
37+
{
38+
"type": "quiver",
39+
"name": "large arrows",
40+
"x": [0, 1, 2],
41+
"y": [2, 2, 2],
42+
"u": [1, 1, 1],
43+
"v": [1, 1, 1],
44+
"sizemode": "scaled",
45+
"sizeref": 0.5,
46+
"arrowsize": 2.0,
47+
"anchor": "tail",
48+
"line": {
49+
"color": "green",
50+
"width": 3
51+
},
52+
"showscale": false
53+
}
54+
],
55+
"layout": {
56+
"width": 500,
57+
"height": 600,
58+
"showlegend": true,
59+
"xaxis": {
60+
"range": [-0.5, 2.5]
61+
},
62+
"yaxis": {
63+
"range": [-0.5, 2.5]
64+
}
65+
}
66+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"data": [
3+
{
4+
"type": "quiver",
5+
"x": ["A", "B", "C", "A", "B", "C", "A", "B", "C"],
6+
"y": ["X", "X", "X", "Y", "Y", "Y", "Z", "Z", "Z"],
7+
"u": [1, 0, -1, 1, 0, -1, 1, 0, -1],
8+
"v": [1, 1, 1, 0, 0, 0, -1, -1, -1],
9+
"sizemode": "scaled",
10+
"sizeref": 0.5,
11+
"anchor": "tail",
12+
"line": {
13+
"width": 2
14+
},
15+
"showscale": false
16+
}
17+
],
18+
"layout": {
19+
"title": {"text": "Quiver with Categorical Axes"},
20+
"width": 500,
21+
"height": 500
22+
}
23+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"data": [
3+
{
4+
"type": "quiver",
5+
"x": [0, 1, 2, 0, 1, 2, 0, 1, 2],
6+
"y": [0, 0, 0, 1, 1, 1, 2, 2, 2],
7+
"u": [1, 2, 3, 1, 2, 3, 1, 2, 3],
8+
"v": [1, 1, 1, 2, 2, 2, 3, 3, 3],
9+
"sizemode": "scaled",
10+
"sizeref": 0.3,
11+
"anchor": "tail",
12+
"colorscale": "Viridis",
13+
"showscale": true,
14+
"line": {
15+
"width": 2
16+
},
17+
"colorbar": {
18+
"title": {"text": "Magnitude"}
19+
}
20+
}
21+
],
22+
"layout": {
23+
"width": 600,
24+
"height": 500,
25+
"xaxis": {
26+
"range": [-0.5, 2.5]
27+
},
28+
"yaxis": {
29+
"range": [-0.5, 2.5]
30+
}
31+
}
32+
}

0 commit comments

Comments
 (0)