plotly.js 1.58.0 → 1.58.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -1
- package/dist/README.md +25 -25
- package/dist/plot-schema.json +15 -15
- package/dist/plotly-basic.js +608 -444
- package/dist/plotly-basic.min.js +4 -4
- package/dist/plotly-cartesian.js +725 -561
- package/dist/plotly-cartesian.min.js +4 -4
- package/dist/plotly-finance.js +689 -525
- package/dist/plotly-finance.min.js +4 -4
- package/dist/plotly-geo-assets.js +2 -2
- package/dist/plotly-geo.js +612 -448
- package/dist/plotly-geo.min.js +4 -4
- package/dist/plotly-gl2d.js +790 -626
- package/dist/plotly-gl2d.min.js +10 -10
- package/dist/plotly-gl3d.js +514 -389
- package/dist/plotly-gl3d.min.js +3 -3
- package/dist/plotly-mapbox.js +622 -458
- package/dist/plotly-mapbox.min.js +4 -4
- package/dist/plotly-with-meta.js +988 -856
- package/dist/plotly.js +980 -851
- package/dist/plotly.min.js +3 -3
- package/dist/translation-keys.txt +1 -1
- package/package.json +1 -1
- package/src/components/colorscale/index.js +1 -1
- package/src/components/errorbars/attributes.js +1 -1
- package/src/components/fx/hover.js +1 -1
- package/src/components/sliders/draw.js +1 -1
- package/src/lib/index.js +2 -1
- package/src/lib/preserve_drawing_buffer.js +68 -0
- package/src/plot_api/plot_api.js +19 -15
- package/src/plots/cartesian/autorange.js +33 -64
- package/src/plots/cartesian/axes.js +44 -16
- package/src/plots/cartesian/axis_ids.js +16 -0
- package/src/plots/cartesian/constraints.js +2 -2
- package/src/plots/cartesian/layout_attributes.js +4 -1
- package/src/plots/gl3d/scene.js +16 -18
- package/src/plots/plots.js +61 -22
- package/src/plots/polar/polar.js +2 -0
- package/src/traces/carpet/attributes.js +2 -2
- package/src/traces/carpet/create_i_derivative_evaluator.js +1 -1
- package/src/traces/carpet/plot.js +1 -1
- package/src/traces/carpet/set_convert.js +2 -2
- package/src/traces/carpet/smooth_fill_2d_array.js +1 -1
- package/src/traces/parcats/attributes.js +1 -1
- package/src/traces/scatter/plot.js +1 -1
- package/src/traces/scattercarpet/plot.js +1 -1
- package/src/traces/sunburst/calc.js +3 -1
- package/src/version.js +1 -1
|
@@ -7,7 +7,7 @@ Click to enter Component C title // plots/ternary/ternary.
|
|
|
7
7
|
Click to enter Plot title // plot_api/plot_api.js:604
|
|
8
8
|
Click to enter X axis title // plots/plots.js:333
|
|
9
9
|
Click to enter Y axis title // plots/plots.js:334
|
|
10
|
-
Click to enter radial axis title // plots/polar/polar.js:
|
|
10
|
+
Click to enter radial axis title // plots/polar/polar.js:496
|
|
11
11
|
Compare data on hover // components/modebar/buttons.js:237
|
|
12
12
|
Double-click on legend to isolate one trace // components/legend/handle_click.js:27
|
|
13
13
|
Double-click to zoom back out // plots/cartesian/dragbox.js:1172
|
package/package.json
CHANGED
|
@@ -25,7 +25,7 @@ module.exports = {
|
|
|
25
25
|
calc: require('./calc'),
|
|
26
26
|
|
|
27
27
|
// ./scales.js is required in lib/coerce.js ;
|
|
28
|
-
// it needs to be a
|
|
28
|
+
// it needs to be a separate module to avoid circular a dependency
|
|
29
29
|
scales: scales.scales,
|
|
30
30
|
defaultScale: scales.defaultScale,
|
|
31
31
|
getScale: scales.get,
|
|
@@ -32,7 +32,7 @@ module.exports = {
|
|
|
32
32
|
'If *percent*, the bar lengths correspond to a percentage of',
|
|
33
33
|
'underlying data. Set this percentage in `value`.',
|
|
34
34
|
|
|
35
|
-
'If *sqrt*, the bar lengths correspond to the
|
|
35
|
+
'If *sqrt*, the bar lengths correspond to the square of the',
|
|
36
36
|
'underlying data.',
|
|
37
37
|
|
|
38
38
|
'If *data*, the bar lengths are set with data set `array`.'
|
|
@@ -1306,7 +1306,7 @@ function getHoverLabelText(d, showCommonLabel, hovermode, fullLayout, t0, g) {
|
|
|
1306
1306
|
|
|
1307
1307
|
// Make groups of touching points, and within each group
|
|
1308
1308
|
// move each point so that no labels overlap, but the average
|
|
1309
|
-
// label position is the same as it was before moving.
|
|
1309
|
+
// label position is the same as it was before moving. Incidentally,
|
|
1310
1310
|
// this is equivalent to saying all the labels are on equal linear
|
|
1311
1311
|
// springs about their initial position. Initially, each point is
|
|
1312
1312
|
// its own group, but as we find overlaps we will clump the points.
|
|
@@ -571,7 +571,7 @@ function setGripPosition(sliderGroup, sliderOpts, doTransition) {
|
|
|
571
571
|
.ease(sliderOpts.transition.easing);
|
|
572
572
|
}
|
|
573
573
|
|
|
574
|
-
// Drawing.setTranslate doesn't work here
|
|
574
|
+
// Drawing.setTranslate doesn't work here because of the transition duck-typing.
|
|
575
575
|
// It's also not necessary because there are no other transitions to preserve.
|
|
576
576
|
el.attr('transform', strTranslate(x - constants.gripWidth * 0.5, sliderOpts._dims.currentValueTotalHeight));
|
|
577
577
|
}
|
package/src/lib/index.js
CHANGED
|
@@ -154,6 +154,7 @@ lib.getElementAndAncestors = domModule.getElementAndAncestors;
|
|
|
154
154
|
lib.equalDomRects = domModule.equalDomRects;
|
|
155
155
|
|
|
156
156
|
lib.clearResponsive = require('./clear_responsive');
|
|
157
|
+
lib.preserveDrawingBuffer = require('./preserve_drawing_buffer');
|
|
157
158
|
|
|
158
159
|
lib.makeTraceGroups = require('./make_trace_groups');
|
|
159
160
|
|
|
@@ -864,7 +865,7 @@ lib.objectFromPath = function(path, value) {
|
|
|
864
865
|
* lib.expandObjectPaths({'foo[1].bar': 10, 'foo[0].bar': 20});
|
|
865
866
|
* => { foo: [{bar: 10}, {bar: 20}] }
|
|
866
867
|
*
|
|
867
|
-
* It does NOT, however, merge
|
|
868
|
+
* It does NOT, however, merge multiple multiply-nested arrays::
|
|
868
869
|
*
|
|
869
870
|
* lib.expandObjectPaths({'marker[1].range[1]': 5, 'marker[1].range[0]': 4})
|
|
870
871
|
* => { marker: [null, {range: 4}] }
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2012-2020, Plotly, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
var isNumeric = require('fast-isnumeric');
|
|
12
|
+
var isMobileOrTablet = require('is-mobile');
|
|
13
|
+
|
|
14
|
+
module.exports = function preserveDrawingBuffer(opts) {
|
|
15
|
+
var ua;
|
|
16
|
+
|
|
17
|
+
if(opts && opts.hasOwnProperty('userAgent')) {
|
|
18
|
+
ua = opts.userAgent;
|
|
19
|
+
} else {
|
|
20
|
+
ua = getUserAgent();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if(typeof ua !== 'string') return true;
|
|
24
|
+
|
|
25
|
+
var enable = isMobileOrTablet({
|
|
26
|
+
ua: { headers: {'user-agent': ua }},
|
|
27
|
+
tablet: true,
|
|
28
|
+
featureDetect: false
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if(!enable) {
|
|
32
|
+
var allParts = ua.split(' ');
|
|
33
|
+
for(var i = 1; i < allParts.length; i++) {
|
|
34
|
+
var part = allParts[i];
|
|
35
|
+
if(part.indexOf('Safari') !== -1) {
|
|
36
|
+
// find Safari version
|
|
37
|
+
for(var k = i - 1; k > -1; k--) {
|
|
38
|
+
var prevPart = allParts[k];
|
|
39
|
+
if(prevPart.substr(0, 8) === 'Version/') {
|
|
40
|
+
var v = prevPart.substr(8).split('.')[0];
|
|
41
|
+
if(isNumeric(v)) v = +v;
|
|
42
|
+
if(v >= 13) return true;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return enable;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
function getUserAgent() {
|
|
53
|
+
// similar to https://github.com/juliangruber/is-mobile/blob/91ca39ccdd4cfc5edfb5391e2515b923a730fbea/index.js#L14-L17
|
|
54
|
+
var ua;
|
|
55
|
+
if(typeof navigator !== 'undefined') {
|
|
56
|
+
ua = navigator.userAgent;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if(
|
|
60
|
+
ua &&
|
|
61
|
+
ua.headers &&
|
|
62
|
+
typeof ua.headers['user-agent'] === 'string'
|
|
63
|
+
) {
|
|
64
|
+
ua = ua.headers['user-agent'];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return ua;
|
|
68
|
+
}
|
package/src/plot_api/plot_api.js
CHANGED
|
@@ -1948,7 +1948,9 @@ function axRangeSupplyDefaultsByPass(gd, flags, specs) {
|
|
|
1948
1948
|
var axIn = gd.layout[axName];
|
|
1949
1949
|
var axOut = fullLayout[axName];
|
|
1950
1950
|
axOut.autorange = axIn.autorange;
|
|
1951
|
-
|
|
1951
|
+
if(axIn.range) {
|
|
1952
|
+
axOut.range = axIn.range.slice();
|
|
1953
|
+
}
|
|
1952
1954
|
axOut.cleanRange();
|
|
1953
1955
|
|
|
1954
1956
|
if(axOut._matchGroup) {
|
|
@@ -2735,16 +2737,6 @@ function react(gd, data, layout, config) {
|
|
|
2735
2737
|
|
|
2736
2738
|
applyUIRevisions(gd.data, gd.layout, oldFullData, oldFullLayout);
|
|
2737
2739
|
|
|
2738
|
-
var allNames = Object.getOwnPropertyNames(oldFullLayout);
|
|
2739
|
-
for(var q = 0; q < allNames.length; q++) {
|
|
2740
|
-
var name = allNames[q];
|
|
2741
|
-
var start = name.substring(0, 5);
|
|
2742
|
-
if(start === 'xaxis' || start === 'yaxis') {
|
|
2743
|
-
var emptyCategories = oldFullLayout[name]._emptyCategories;
|
|
2744
|
-
if(emptyCategories) emptyCategories();
|
|
2745
|
-
}
|
|
2746
|
-
}
|
|
2747
|
-
|
|
2748
2740
|
// "true" skips updating calcdata and remapping arrays from calcTransforms,
|
|
2749
2741
|
// which supplyDefaults usually does at the end, but we may need to NOT do
|
|
2750
2742
|
// if the diff (which we haven't determined yet) says we'll recalc
|
|
@@ -2770,10 +2762,22 @@ function react(gd, data, layout, config) {
|
|
|
2770
2762
|
|
|
2771
2763
|
if(updateAutosize(gd)) relayoutFlags.layoutReplot = true;
|
|
2772
2764
|
|
|
2773
|
-
// clear calcdata if required
|
|
2774
|
-
if(restyleFlags.calc || relayoutFlags.calc)
|
|
2765
|
+
// clear calcdata and empty categories if required
|
|
2766
|
+
if(restyleFlags.calc || relayoutFlags.calc) {
|
|
2767
|
+
gd.calcdata = undefined;
|
|
2768
|
+
var allNames = Object.getOwnPropertyNames(newFullLayout);
|
|
2769
|
+
for(var q = 0; q < allNames.length; q++) {
|
|
2770
|
+
var name = allNames[q];
|
|
2771
|
+
var start = name.substring(0, 5);
|
|
2772
|
+
if(start === 'xaxis' || start === 'yaxis') {
|
|
2773
|
+
var emptyCategories = newFullLayout[name]._emptyCategories;
|
|
2774
|
+
if(emptyCategories) emptyCategories();
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2775
2777
|
// otherwise do the calcdata updates and calcTransform array remaps that we skipped earlier
|
|
2776
|
-
else
|
|
2778
|
+
} else {
|
|
2779
|
+
Plots.supplyDefaultsUpdateCalc(gd.calcdata, newFullData);
|
|
2780
|
+
}
|
|
2777
2781
|
|
|
2778
2782
|
// Note: what restyle/relayout use impliedEdits and clearAxisTypes for
|
|
2779
2783
|
// must be handled by the user when using Plotly.react.
|
|
@@ -3227,7 +3231,7 @@ function animate(gd, frameOrGroupNameOrFrameList, animationOpts) {
|
|
|
3227
3231
|
}
|
|
3228
3232
|
|
|
3229
3233
|
// Execute a callback after the wrapper function has been called n times.
|
|
3230
|
-
// This is used to defer the resolution until a transition has
|
|
3234
|
+
// This is used to defer the resolution until a transition has resolved *and*
|
|
3231
3235
|
// the frame has completed. If it's not done this way, then we get a race
|
|
3232
3236
|
// condition in which the animation might resolve before a transition is complete
|
|
3233
3237
|
// or vice versa.
|
|
@@ -14,7 +14,9 @@ var Lib = require('../../lib');
|
|
|
14
14
|
var FP_SAFE = require('../../constants/numerical').FP_SAFE;
|
|
15
15
|
var Registry = require('../../registry');
|
|
16
16
|
|
|
17
|
-
var
|
|
17
|
+
var axIds = require('./axis_ids');
|
|
18
|
+
var getFromId = axIds.getFromId;
|
|
19
|
+
var isLinked = axIds.isLinked;
|
|
18
20
|
|
|
19
21
|
module.exports = {
|
|
20
22
|
getAutoRange: getAutoRange,
|
|
@@ -56,8 +58,9 @@ function getAutoRange(gd, ax) {
|
|
|
56
58
|
var i, j;
|
|
57
59
|
var newRange = [];
|
|
58
60
|
|
|
59
|
-
var
|
|
60
|
-
var
|
|
61
|
+
var fullLayout = gd._fullLayout;
|
|
62
|
+
var getPadMin = makePadFn(fullLayout, ax, 0);
|
|
63
|
+
var getPadMax = makePadFn(fullLayout, ax, 1);
|
|
61
64
|
var extremes = concatExtremes(gd, ax);
|
|
62
65
|
var minArray = extremes.min;
|
|
63
66
|
var maxArray = extremes.max;
|
|
@@ -117,8 +120,8 @@ function getAutoRange(gd, ax) {
|
|
|
117
120
|
} else if(dv / axLen > mbest) {
|
|
118
121
|
// in case of padding longer than the axis
|
|
119
122
|
// at least include the unpadded data values.
|
|
120
|
-
minbest = {val: minpt.val,
|
|
121
|
-
maxbest = {val: maxpt.val,
|
|
123
|
+
minbest = {val: minpt.val, nopad: 1};
|
|
124
|
+
maxbest = {val: maxpt.val, nopad: 1};
|
|
122
125
|
mbest = dv / axLen;
|
|
123
126
|
}
|
|
124
127
|
}
|
|
@@ -155,17 +158,17 @@ function getAutoRange(gd, ax) {
|
|
|
155
158
|
} else {
|
|
156
159
|
if(toZero) {
|
|
157
160
|
if(minbest.val >= 0) {
|
|
158
|
-
minbest = {val: 0,
|
|
161
|
+
minbest = {val: 0, nopad: 1};
|
|
159
162
|
}
|
|
160
163
|
if(maxbest.val <= 0) {
|
|
161
|
-
maxbest = {val: 0,
|
|
164
|
+
maxbest = {val: 0, nopad: 1};
|
|
162
165
|
}
|
|
163
166
|
} else if(nonNegative) {
|
|
164
167
|
if(minbest.val - mbest * getPadMin(minbest) < 0) {
|
|
165
|
-
minbest = {val: 0,
|
|
168
|
+
minbest = {val: 0, nopad: 1};
|
|
166
169
|
}
|
|
167
170
|
if(maxbest.val <= 0) {
|
|
168
|
-
maxbest = {val: 1,
|
|
171
|
+
maxbest = {val: 1, nopad: 1};
|
|
169
172
|
}
|
|
170
173
|
}
|
|
171
174
|
|
|
@@ -202,13 +205,15 @@ function calcBreaksLength(ax, v0, v1) {
|
|
|
202
205
|
* calculate the pixel padding for ax._min and ax._max entries with
|
|
203
206
|
* optional extrapad as 5% of the total axis length
|
|
204
207
|
*/
|
|
205
|
-
function makePadFn(ax, max) {
|
|
208
|
+
function makePadFn(fullLayout, ax, max) {
|
|
206
209
|
// 5% padding for points that specify extrapad: true
|
|
207
210
|
var extrappad = 0.05 * ax._length;
|
|
208
211
|
|
|
212
|
+
var anchorAxis = ax._anchorAxis || {};
|
|
213
|
+
|
|
209
214
|
if(
|
|
210
215
|
(ax.ticklabelposition || '').indexOf('inside') !== -1 ||
|
|
211
|
-
(
|
|
216
|
+
(anchorAxis.ticklabelposition || '').indexOf('inside') !== -1
|
|
212
217
|
) {
|
|
213
218
|
var axReverse = ax.autorange === 'reversed';
|
|
214
219
|
if(!axReverse) {
|
|
@@ -218,8 +223,11 @@ function makePadFn(ax, max) {
|
|
|
218
223
|
if(axReverse) max = !max;
|
|
219
224
|
}
|
|
220
225
|
|
|
221
|
-
|
|
222
|
-
|
|
226
|
+
var zero = 0;
|
|
227
|
+
if(!isLinked(fullLayout, ax._id)) {
|
|
228
|
+
zero = padInsideLabelsOnAnchorAxis(ax, max);
|
|
229
|
+
}
|
|
230
|
+
extrappad = Math.max(zero, extrappad);
|
|
223
231
|
|
|
224
232
|
// domain-constrained axes: base extrappad on the unconstrained
|
|
225
233
|
// domain so it's consistent as the domain changes
|
|
@@ -228,50 +236,17 @@ function makePadFn(ax, max) {
|
|
|
228
236
|
(ax.domain[1] - ax.domain[0]);
|
|
229
237
|
}
|
|
230
238
|
|
|
231
|
-
return function getPad(pt) {
|
|
239
|
+
return function getPad(pt) {
|
|
240
|
+
if(pt.nopad) return 0;
|
|
241
|
+
return pt.pad + (pt.extrapad ? extrappad : zero);
|
|
242
|
+
};
|
|
232
243
|
}
|
|
233
244
|
|
|
234
245
|
var TEXTPAD = 3;
|
|
235
246
|
|
|
236
|
-
function
|
|
237
|
-
var
|
|
238
|
-
var
|
|
239
|
-
return ticklabelposition.indexOf(str) !== -1;
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
if(!has('inside')) return extrappad;
|
|
243
|
-
var isTop = has('top');
|
|
244
|
-
var isLeft = has('left');
|
|
245
|
-
var isRight = has('right');
|
|
246
|
-
var isBottom = has('bottom');
|
|
247
|
-
var isAligned = isBottom || isLeft || isTop || isRight;
|
|
248
|
-
|
|
249
|
-
if(
|
|
250
|
-
(max && (isLeft || isBottom)) ||
|
|
251
|
-
(!max && (isRight || isTop))
|
|
252
|
-
) {
|
|
253
|
-
return extrappad;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// increase padding to make more room for inside tick labels of the axis
|
|
257
|
-
var fontSize = ax.tickfont ? ax.tickfont.size : 12;
|
|
258
|
-
var isX = ax._id.charAt(0) === 'x';
|
|
259
|
-
var morePad = (isX ? 1.2 : 0.6) * fontSize;
|
|
260
|
-
|
|
261
|
-
if(isAligned) {
|
|
262
|
-
morePad *= 2;
|
|
263
|
-
morePad += (ax.tickwidth || 0) / 2;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
morePad += TEXTPAD;
|
|
267
|
-
|
|
268
|
-
extrappad = Math.max(extrappad, morePad);
|
|
269
|
-
|
|
270
|
-
return extrappad;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
function adjustPadForInsideLabelsOnAnchorAxis(extrappad, ax, max) {
|
|
274
|
-
var anchorAxis = (ax._anchorAxis || {});
|
|
247
|
+
function padInsideLabelsOnAnchorAxis(ax, max) {
|
|
248
|
+
var pad = 0;
|
|
249
|
+
var anchorAxis = ax._anchorAxis || {};
|
|
275
250
|
if((anchorAxis.ticklabelposition || '').indexOf('inside') !== -1) {
|
|
276
251
|
// increase padding to make more room for inside tick labels of the counter axis
|
|
277
252
|
if((
|
|
@@ -287,7 +262,6 @@ function adjustPadForInsideLabelsOnAnchorAxis(extrappad, ax, max) {
|
|
|
287
262
|
)) {
|
|
288
263
|
var isX = ax._id.charAt(0) === 'x';
|
|
289
264
|
|
|
290
|
-
var morePad = 0;
|
|
291
265
|
if(anchorAxis._vals) {
|
|
292
266
|
var rad = Lib.deg2rad(anchorAxis._tickAngles[anchorAxis._id + 'tick'] || 0);
|
|
293
267
|
var cosA = Math.abs(Math.cos(rad));
|
|
@@ -296,29 +270,24 @@ function adjustPadForInsideLabelsOnAnchorAxis(extrappad, ax, max) {
|
|
|
296
270
|
// use bounding boxes
|
|
297
271
|
anchorAxis._vals.forEach(function(t) {
|
|
298
272
|
if(t.bb) {
|
|
299
|
-
var w = t.bb.width;
|
|
300
|
-
var h = t.bb.height;
|
|
273
|
+
var w = 2 * TEXTPAD + t.bb.width;
|
|
274
|
+
var h = 2 * TEXTPAD + t.bb.height;
|
|
301
275
|
|
|
302
|
-
|
|
276
|
+
pad = Math.max(pad, isX ?
|
|
303
277
|
Math.max(w * cosA, h * sinA) :
|
|
304
278
|
Math.max(h * cosA, w * sinA)
|
|
305
279
|
);
|
|
306
|
-
|
|
307
|
-
// add extra pad around label
|
|
308
|
-
morePad += 3;
|
|
309
280
|
}
|
|
310
281
|
});
|
|
311
282
|
}
|
|
312
283
|
|
|
313
284
|
if(anchorAxis.ticks === 'inside' && anchorAxis.ticklabelposition === 'inside') {
|
|
314
|
-
|
|
285
|
+
pad += anchorAxis.ticklen || 0;
|
|
315
286
|
}
|
|
316
|
-
|
|
317
|
-
extrappad = Math.max(extrappad, morePad);
|
|
318
287
|
}
|
|
319
288
|
}
|
|
320
289
|
|
|
321
|
-
return
|
|
290
|
+
return pad;
|
|
322
291
|
}
|
|
323
292
|
|
|
324
293
|
function concatExtremes(gd, ax, noMatch) {
|
|
@@ -56,6 +56,10 @@ axes.setConvert = require('./set_convert');
|
|
|
56
56
|
var autoType = require('./axis_autotype');
|
|
57
57
|
|
|
58
58
|
var axisIds = require('./axis_ids');
|
|
59
|
+
var idSort = axisIds.idSort;
|
|
60
|
+
var isLinked = axisIds.isLinked;
|
|
61
|
+
|
|
62
|
+
// tight coupling to chart studio
|
|
59
63
|
axes.id2name = axisIds.id2name;
|
|
60
64
|
axes.name2id = axisIds.name2id;
|
|
61
65
|
axes.cleanId = axisIds.cleanId;
|
|
@@ -1445,9 +1449,23 @@ function formatDate(ax, out, hover, extraPrecision) {
|
|
|
1445
1449
|
// except for year headPart: turn this into "Jan 1, 2000" etc.
|
|
1446
1450
|
if(tr === 'd') dateStr += ', ' + headStr;
|
|
1447
1451
|
else dateStr = headStr + (dateStr ? ', ' + dateStr : '');
|
|
1448
|
-
} else
|
|
1449
|
-
|
|
1450
|
-
|
|
1452
|
+
} else {
|
|
1453
|
+
if(
|
|
1454
|
+
!ax._inCalcTicks ||
|
|
1455
|
+
ax._prevDateHead !== headStr
|
|
1456
|
+
) {
|
|
1457
|
+
ax._prevDateHead = headStr;
|
|
1458
|
+
dateStr += '<br>' + headStr;
|
|
1459
|
+
} else {
|
|
1460
|
+
var isInside = (ax.ticklabelposition || '').indexOf('inside') !== -1;
|
|
1461
|
+
var side = ax._realSide || ax.side; // polar mocks the side of the radial axis
|
|
1462
|
+
if(
|
|
1463
|
+
(!isInside && side === 'top') ||
|
|
1464
|
+
(isInside && side === 'bottom')
|
|
1465
|
+
) {
|
|
1466
|
+
dateStr += '<br> ';
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1451
1469
|
}
|
|
1452
1470
|
}
|
|
1453
1471
|
|
|
@@ -2893,7 +2911,7 @@ axes.drawZeroLine = function(gd, ax, opts) {
|
|
|
2893
2911
|
// If several zerolines enter at the same time we will sort once per,
|
|
2894
2912
|
// but generally this should be a minimal overhead.
|
|
2895
2913
|
opts.layer.selectAll('path').sort(function(da, db) {
|
|
2896
|
-
return
|
|
2914
|
+
return idSort(da.id, db.id);
|
|
2897
2915
|
});
|
|
2898
2916
|
});
|
|
2899
2917
|
|
|
@@ -3191,7 +3209,8 @@ axes.drawLabels = function(gd, ax, opts) {
|
|
|
3191
3209
|
var anchorAx = ax._anchorAxis;
|
|
3192
3210
|
if(
|
|
3193
3211
|
anchorAx && anchorAx.autorange &&
|
|
3194
|
-
(ax.ticklabelposition || '').indexOf('inside') !== -1
|
|
3212
|
+
(ax.ticklabelposition || '').indexOf('inside') !== -1 &&
|
|
3213
|
+
!isLinked(fullLayout, ax._id)
|
|
3195
3214
|
) {
|
|
3196
3215
|
if(!fullLayout._insideTickLabelsAutorange) {
|
|
3197
3216
|
fullLayout._insideTickLabelsAutorange = {};
|
|
@@ -3334,27 +3353,36 @@ function drawTitle(gd, ax) {
|
|
|
3334
3353
|
var axId = ax._id;
|
|
3335
3354
|
var axLetter = axId.charAt(0);
|
|
3336
3355
|
var fontSize = ax.title.font.size;
|
|
3337
|
-
|
|
3338
3356
|
var titleStandoff;
|
|
3339
3357
|
|
|
3340
3358
|
if(ax.title.hasOwnProperty('standoff')) {
|
|
3341
3359
|
titleStandoff = ax._depth + ax.title.standoff + approxTitleDepth(ax);
|
|
3342
3360
|
} else {
|
|
3361
|
+
var isInside = (ax.ticklabelposition || '').indexOf('inside') !== -1;
|
|
3362
|
+
|
|
3343
3363
|
if(ax.type === 'multicategory') {
|
|
3344
3364
|
titleStandoff = ax._depth;
|
|
3345
3365
|
} else {
|
|
3346
|
-
var offsetBase = 1.5;
|
|
3347
|
-
|
|
3366
|
+
var offsetBase = 1.5 * fontSize;
|
|
3367
|
+
if(isInside) {
|
|
3368
|
+
offsetBase = 0.5 * fontSize;
|
|
3369
|
+
if(ax.ticks === 'outside') {
|
|
3370
|
+
offsetBase += ax.ticklen;
|
|
3371
|
+
}
|
|
3372
|
+
}
|
|
3373
|
+
titleStandoff = 10 + offsetBase + (ax.linewidth ? ax.linewidth - 1 : 0);
|
|
3348
3374
|
}
|
|
3349
3375
|
|
|
3350
|
-
if(
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3376
|
+
if(!isInside) {
|
|
3377
|
+
if(axLetter === 'x') {
|
|
3378
|
+
titleStandoff += ax.side === 'top' ?
|
|
3379
|
+
fontSize * (ax.showticklabels ? 1 : 0) :
|
|
3380
|
+
fontSize * (ax.showticklabels ? 1.5 : 0.5);
|
|
3381
|
+
} else {
|
|
3382
|
+
titleStandoff += ax.side === 'right' ?
|
|
3383
|
+
fontSize * (ax.showticklabels ? 1 : 0.5) :
|
|
3384
|
+
fontSize * (ax.showticklabels ? 0.5 : 0);
|
|
3385
|
+
}
|
|
3358
3386
|
}
|
|
3359
3387
|
}
|
|
3360
3388
|
|
|
@@ -136,3 +136,19 @@ exports.ref2id = function(ar) {
|
|
|
136
136
|
// return the axis ID. Otherwise it returns false.
|
|
137
137
|
return (/^[xyz]/.test(ar)) ? ar.split(' ')[0] : false;
|
|
138
138
|
};
|
|
139
|
+
|
|
140
|
+
function isFound(axId, list) {
|
|
141
|
+
if(list && list.length) {
|
|
142
|
+
for(var i = 0; i < list.length; i++) {
|
|
143
|
+
if(list[i][axId]) return true;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
exports.isLinked = function(fullLayout, axId) {
|
|
150
|
+
return (
|
|
151
|
+
isFound(axId, fullLayout._axisMatchGroups) ||
|
|
152
|
+
isFound(axId, fullLayout._axisConstraintGroups)
|
|
153
|
+
);
|
|
154
|
+
};
|
|
@@ -565,8 +565,8 @@ exports.enforce = function enforce(gd) {
|
|
|
565
565
|
// *are* expanding to the full domain
|
|
566
566
|
var outerMin = rangeCenter - halfRange * factor * 1.0001;
|
|
567
567
|
var outerMax = rangeCenter + halfRange * factor * 1.0001;
|
|
568
|
-
var getPadMin = autorange.makePadFn(ax, 0);
|
|
569
|
-
var getPadMax = autorange.makePadFn(ax, 1);
|
|
568
|
+
var getPadMin = autorange.makePadFn(fullLayout, ax, 0);
|
|
569
|
+
var getPadMax = autorange.makePadFn(fullLayout, ax, 1);
|
|
570
570
|
|
|
571
571
|
updateDomain(ax, factor);
|
|
572
572
|
var m = Math.abs(ax._m);
|
|
@@ -525,7 +525,10 @@ module.exports = {
|
|
|
525
525
|
'top or bottom has no effect on x axes or when `ticklabelmode` is set to *period*.',
|
|
526
526
|
'Similarly',
|
|
527
527
|
'left or right has no effect on y axes or when `ticklabelmode` is set to *period*.',
|
|
528
|
-
'Has no effect on *multicategory* axes or when `tickson` is set to *boundaries*.'
|
|
528
|
+
'Has no effect on *multicategory* axes or when `tickson` is set to *boundaries*.',
|
|
529
|
+
'When used on axes linked by `matches` or `scaleanchor`,',
|
|
530
|
+
'no extra padding for inside labels would be added by autorange,',
|
|
531
|
+
'so that the scales could match.'
|
|
529
532
|
].join(' ')
|
|
530
533
|
},
|
|
531
534
|
mirror: {
|
package/src/plots/gl3d/scene.js
CHANGED
|
@@ -18,6 +18,7 @@ var passiveSupported = require('has-passive-events');
|
|
|
18
18
|
|
|
19
19
|
var Registry = require('../../registry');
|
|
20
20
|
var Lib = require('../../lib');
|
|
21
|
+
var preserveDrawingBuffer = Lib.preserveDrawingBuffer();
|
|
21
22
|
|
|
22
23
|
var Axes = require('../../plots/cartesian/axes');
|
|
23
24
|
var Fx = require('../../components/fx');
|
|
@@ -30,9 +31,6 @@ var createAxesOptions = require('./layout/convert');
|
|
|
30
31
|
var createSpikeOptions = require('./layout/spikes');
|
|
31
32
|
var computeTickMarks = require('./layout/tick_marks');
|
|
32
33
|
|
|
33
|
-
var isMobile = require('is-mobile')({ tablet: true, featureDetect: true });
|
|
34
|
-
|
|
35
|
-
|
|
36
34
|
var STATIC_CANVAS, STATIC_CONTEXT;
|
|
37
35
|
|
|
38
36
|
function Scene(options, fullLayout) {
|
|
@@ -98,7 +96,7 @@ proto.prepareOptions = function() {
|
|
|
98
96
|
canvas: scene.canvas,
|
|
99
97
|
gl: scene.gl,
|
|
100
98
|
glOptions: {
|
|
101
|
-
preserveDrawingBuffer:
|
|
99
|
+
preserveDrawingBuffer: preserveDrawingBuffer,
|
|
102
100
|
premultipliedAlpha: true,
|
|
103
101
|
antialias: true
|
|
104
102
|
},
|
|
@@ -148,26 +146,26 @@ proto.tryCreatePlot = function() {
|
|
|
148
146
|
try {
|
|
149
147
|
scene.glplot = createPlot(opts);
|
|
150
148
|
} catch(e) {
|
|
151
|
-
if(scene.staticMode || !firstInit) {
|
|
149
|
+
if(scene.staticMode || !firstInit || preserveDrawingBuffer) {
|
|
152
150
|
success = false;
|
|
153
151
|
} else { // try second time
|
|
152
|
+
// enable preserveDrawingBuffer setup
|
|
153
|
+
// in case is-mobile not detecting the right device
|
|
154
|
+
Lib.warn([
|
|
155
|
+
'webgl setup failed possibly due to',
|
|
156
|
+
'false preserveDrawingBuffer config.',
|
|
157
|
+
'The mobile/tablet device may not be detected by is-mobile module.',
|
|
158
|
+
'Enabling preserveDrawingBuffer in second attempt to create webgl scene...'
|
|
159
|
+
].join(' '));
|
|
160
|
+
|
|
154
161
|
try {
|
|
155
|
-
// invert preserveDrawingBuffer
|
|
156
|
-
|
|
157
|
-
'webgl setup failed possibly due to',
|
|
158
|
-
isMobile ? 'disabling' : 'enabling',
|
|
159
|
-
'preserveDrawingBuffer config.',
|
|
160
|
-
'The device may not be supported by is-mobile module!',
|
|
161
|
-
'Inverting preserveDrawingBuffer option in second attempt to create webgl scene.'
|
|
162
|
-
].join(' '));
|
|
163
|
-
|
|
164
|
-
// invert is-mobile
|
|
165
|
-
isMobile = opts.glOptions.preserveDrawingBuffer = !opts.glOptions.preserveDrawingBuffer;
|
|
162
|
+
// invert preserveDrawingBuffer
|
|
163
|
+
preserveDrawingBuffer = opts.glOptions.preserveDrawingBuffer = true;
|
|
166
164
|
|
|
167
165
|
scene.glplot = createPlot(opts);
|
|
168
166
|
} catch(e) {
|
|
169
|
-
// revert changes to
|
|
170
|
-
|
|
167
|
+
// revert changes to preserveDrawingBuffer
|
|
168
|
+
preserveDrawingBuffer = opts.glOptions.preserveDrawingBuffer = false;
|
|
171
169
|
|
|
172
170
|
success = false;
|
|
173
171
|
}
|