-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
Copy pathcross_trace_calc.js
133 lines (108 loc) · 4.09 KB
/
cross_trace_calc.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/**
* Copyright 2012-2018, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
var Axes = require('../../plots/cartesian/axes');
var Lib = require('../../lib');
var orientations = ['v', 'h'];
function crossTraceCalc(gd, plotinfo) {
var calcdata = gd.calcdata;
var xa = plotinfo.xaxis;
var ya = plotinfo.yaxis;
for(var i = 0; i < orientations.length; i++) {
var orientation = orientations[i];
var posAxis = orientation === 'h' ? ya : xa;
var boxList = [];
var minPad = 0;
var maxPad = 0;
// make list of boxes / candlesticks
// For backward compatibility, candlesticks are treated as if they *are* box traces here
for(var j = 0; j < calcdata.length; j++) {
var cd = calcdata[j];
var t = cd[0].t;
var trace = cd[0].trace;
if(trace.visible === true &&
(trace.type === 'box' || trace.type === 'candlestick') &&
!t.empty &&
(trace.orientation || 'v') === orientation &&
trace.xaxis === xa._id &&
trace.yaxis === ya._id
) {
boxList.push(j);
if(trace.boxpoints) {
minPad = Math.max(minPad, trace.jitter - trace.pointpos - 1);
maxPad = Math.max(maxPad, trace.jitter + trace.pointpos - 1);
}
}
}
setPositionOffset('box', gd, boxList, posAxis, [minPad, maxPad]);
}
}
function setPositionOffset(traceType, gd, boxList, posAxis, pad) {
var calcdata = gd.calcdata;
var fullLayout = gd._fullLayout;
var pointList = [];
// N.B. reused in violin
var numKey = traceType === 'violin' ? '_numViolins' : '_numBoxes';
var i, j, calcTrace;
// make list of box points
for(i = 0; i < boxList.length; i++) {
calcTrace = calcdata[boxList[i]];
for(j = 0; j < calcTrace.length; j++) {
pointList.push(calcTrace[j].pos);
}
}
if(!pointList.length) return;
// box plots - update dPos based on multiple traces
// and then use for posAxis autorange
var boxdv = Lib.distinctVals(pointList);
var dPos = boxdv.minDiff / 2;
// if there's no duplication of x points,
// disable 'group' mode by setting counter to 1
if(pointList.length === boxdv.vals.length) {
fullLayout[numKey] = 1;
}
// check for forced minimum dtick
Axes.minDtick(posAxis, boxdv.minDiff, boxdv.vals[0], true);
var gap = fullLayout[traceType + 'gap'];
var groupgap = fullLayout[traceType + 'groupgap'];
var padfactor = (1 - gap) * (1 - groupgap) * dPos / fullLayout[numKey];
// Find maximum trace width
// we baseline this at dPos
var max_half_width = dPos;
for(i = 0; i < boxList.length; i++) {
calcTrace = calcdata[boxList[i]];
if(calcTrace[0].trace.vwidth) {
if(calcTrace[0].trace.vwidth / 2 > max_half_width) {
max_half_width = calcTrace[0].trace.vwidth / 2;
}
}
}
// autoscale the x axis - including space for points if they're off the side
// TODO: this will overdo it if the outermost boxes don't have
// their points as far out as the other boxes
var extremes = Axes.findExtremes(posAxis, boxdv.vals, {
vpadminus: max_half_width + pad[0] * padfactor,
vpadplus: max_half_width + pad[1] * padfactor
});
for(i = 0; i < boxList.length; i++) {
calcTrace = calcdata[boxList[i]];
// set the width of all boxes
// override dPos with trace.width if present
if(calcTrace[0].trace && calcTrace[0].trace.vwidth) {
calcTrace[0].t.dPos = calcTrace[0].trace.vwidth / 2;
} else {
calcTrace[0].t.dPos = dPos;
}
// link extremes to all boxes
calcTrace[0].trace._extremes[posAxis._id] = extremes;
}
}
module.exports = {
crossTraceCalc: crossTraceCalc,
setPositionOffset: setPositionOffset
};