plotly.js 2.7.0 → 2.8.3
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 +32 -0
- package/README.md +3 -3
- package/dist/README.md +26 -26
- package/dist/plot-schema.json +898 -407
- package/dist/plotly-basic.js +497 -186
- package/dist/plotly-basic.min.js +4 -4
- package/dist/plotly-cartesian.js +907 -329
- package/dist/plotly-cartesian.min.js +3 -3
- package/dist/plotly-finance.js +500 -188
- package/dist/plotly-finance.min.js +4 -4
- package/dist/plotly-geo-assets.js +2 -2
- package/dist/plotly-geo.js +486 -184
- package/dist/plotly-geo.min.js +4 -4
- package/dist/plotly-gl2d.js +505 -187
- package/dist/plotly-gl2d.min.js +2 -2
- package/dist/plotly-gl3d.js +486 -184
- package/dist/plotly-gl3d.min.js +2 -2
- package/dist/plotly-mapbox.js +486 -184
- package/dist/plotly-mapbox.min.js +2 -2
- package/dist/plotly-strict.js +1125 -547
- package/dist/plotly-strict.min.js +3 -3
- package/dist/plotly-with-meta.js +1214 -609
- package/dist/plotly.js +1179 -601
- package/dist/plotly.min.js +10 -10
- package/package.json +4 -4
- package/src/components/colorbar/attributes.js +29 -20
- package/src/components/colorbar/defaults.js +30 -8
- package/src/components/colorbar/draw.js +374 -128
- package/src/components/fx/hover.js +5 -2
- package/src/components/fx/hoverlabel_defaults.js +4 -2
- package/src/components/fx/layout_attributes.js +14 -4
- package/src/components/fx/layout_defaults.js +2 -0
- package/src/components/legend/attributes.js +7 -0
- package/src/components/legend/defaults.js +24 -7
- package/src/components/titles/index.js +8 -2
- package/src/plot_api/plot_api.js +1 -1
- package/src/plots/font_attributes.js +3 -0
- package/src/plots/layout_attributes.js +1 -0
- package/src/plots/plots.js +7 -15
- package/src/traces/bar/plot.js +8 -1
- package/src/traces/contour/attributes.js +12 -0
- package/src/traces/contour/defaults.js +9 -1
- package/src/traces/heatmap/attributes.js +16 -0
- package/src/traces/heatmap/defaults.js +2 -0
- package/src/traces/heatmap/label_defaults.js +13 -0
- package/src/traces/heatmap/plot.js +205 -4
- package/src/traces/histogram/calc.js +3 -2
- package/src/traces/histogram2d/attributes.js +8 -0
- package/src/traces/histogram2d/defaults.js +4 -0
- package/src/traces/histogram2dcontour/attributes.js +3 -1
- package/src/traces/histogram2dcontour/defaults.js +8 -1
- package/src/traces/pie/calc.js +3 -1
- package/src/version.js +1 -1
- package/tasks/test_mock.js +1 -0
|
@@ -167,18 +167,20 @@ function makeColorBarData(gd) {
|
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
function drawColorBar(g, opts, gd) {
|
|
170
|
+
var isVertical = opts.orientation === 'v';
|
|
170
171
|
var len = opts.len;
|
|
171
172
|
var lenmode = opts.lenmode;
|
|
172
173
|
var thickness = opts.thickness;
|
|
173
174
|
var thicknessmode = opts.thicknessmode;
|
|
174
175
|
var outlinewidth = opts.outlinewidth;
|
|
175
176
|
var borderwidth = opts.borderwidth;
|
|
177
|
+
var bgcolor = opts.bgcolor;
|
|
176
178
|
var xanchor = opts.xanchor;
|
|
177
179
|
var yanchor = opts.yanchor;
|
|
178
180
|
var xpad = opts.xpad;
|
|
179
181
|
var ypad = opts.ypad;
|
|
180
182
|
var optsX = opts.x;
|
|
181
|
-
var optsY = opts.y;
|
|
183
|
+
var optsY = isVertical ? opts.y : 1 - opts.y;
|
|
182
184
|
|
|
183
185
|
var fullLayout = gd._fullLayout;
|
|
184
186
|
var gs = fullLayout._size;
|
|
@@ -209,23 +211,35 @@ function drawColorBar(g, opts, gd) {
|
|
|
209
211
|
// when the colorbar itself is pushing the margins.
|
|
210
212
|
// but then the fractional size is calculated based on the
|
|
211
213
|
// actual graph size, so that the axes will size correctly.
|
|
212
|
-
var thickPx = Math.round(thickness * (thicknessmode === 'fraction' ? gs.w : 1));
|
|
213
|
-
var thickFrac = thickPx / gs.w;
|
|
214
|
-
var lenPx = Math.round(len * (lenmode === 'fraction' ? gs.h : 1));
|
|
215
|
-
var lenFrac = lenPx / gs.h;
|
|
216
|
-
var xpadFrac = xpad / gs.w;
|
|
217
|
-
var yExtraPx = (borderwidth + outlinewidth) / 2;
|
|
218
|
-
var ypadFrac = ypad / gs.h;
|
|
214
|
+
var thickPx = Math.round(thickness * (thicknessmode === 'fraction' ? (isVertical ? gs.w : gs.h) : 1));
|
|
215
|
+
var thickFrac = thickPx / (isVertical ? gs.w : gs.h);
|
|
216
|
+
var lenPx = Math.round(len * (lenmode === 'fraction' ? (isVertical ? gs.h : gs.w) : 1));
|
|
217
|
+
var lenFrac = lenPx / (isVertical ? gs.h : gs.w);
|
|
219
218
|
|
|
220
219
|
// x positioning: do it initially just for left anchor,
|
|
221
220
|
// then fix at the end (since we don't know the width yet)
|
|
222
|
-
var uPx = Math.round(
|
|
221
|
+
var uPx = Math.round(isVertical ?
|
|
222
|
+
optsX * gs.w + xpad :
|
|
223
|
+
optsY * gs.h + ypad
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
var xRatio = {center: 0.5, right: 1}[xanchor] || 0;
|
|
227
|
+
var yRatio = {top: 1, middle: 0.5}[yanchor] || 0;
|
|
228
|
+
|
|
223
229
|
// for dragging... this is getting a little muddled...
|
|
224
|
-
var uFrac =
|
|
230
|
+
var uFrac = isVertical ?
|
|
231
|
+
optsX - xRatio * thickFrac :
|
|
232
|
+
optsY - yRatio * thickFrac;
|
|
233
|
+
|
|
234
|
+
// y/x positioning (for v/h) we can do correctly from the start
|
|
235
|
+
var vFrac = isVertical ?
|
|
236
|
+
optsY - yRatio * lenFrac :
|
|
237
|
+
optsX - xRatio * lenFrac;
|
|
225
238
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
239
|
+
var vPx = Math.round(isVertical ?
|
|
240
|
+
gs.h * (1 - vFrac) :
|
|
241
|
+
gs.w * vFrac
|
|
242
|
+
);
|
|
229
243
|
|
|
230
244
|
// stash a few things for makeEditable
|
|
231
245
|
opts._lenFrac = lenFrac;
|
|
@@ -238,12 +252,23 @@ function drawColorBar(g, opts, gd) {
|
|
|
238
252
|
|
|
239
253
|
// position can't go in through supplyDefaults
|
|
240
254
|
// because that restricts it to [0,1]
|
|
241
|
-
ax.position =
|
|
255
|
+
ax.position = thickFrac + (isVertical ?
|
|
256
|
+
optsX + xpad / gs.w :
|
|
257
|
+
optsY + ypad / gs.h
|
|
258
|
+
);
|
|
242
259
|
|
|
243
|
-
|
|
260
|
+
var topOrBottom = ['top', 'bottom'].indexOf(titleSide) !== -1;
|
|
261
|
+
|
|
262
|
+
if(isVertical && topOrBottom) {
|
|
244
263
|
ax.title.side = titleSide;
|
|
245
|
-
ax.titlex = optsX +
|
|
246
|
-
ax.titley = vFrac + (title.side === 'top' ? lenFrac -
|
|
264
|
+
ax.titlex = optsX + xpad / gs.w;
|
|
265
|
+
ax.titley = vFrac + (title.side === 'top' ? lenFrac - ypad / gs.h : ypad / gs.h);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if(!isVertical && !topOrBottom) {
|
|
269
|
+
ax.title.side = titleSide;
|
|
270
|
+
ax.titley = optsY + ypad / gs.h;
|
|
271
|
+
ax.titlex = vFrac + xpad / gs.w; // right side
|
|
247
272
|
}
|
|
248
273
|
|
|
249
274
|
if(line.color && opts.tickmode === 'auto') {
|
|
@@ -268,9 +293,12 @@ function drawColorBar(g, opts, gd) {
|
|
|
268
293
|
|
|
269
294
|
// set domain after init, because we may want to
|
|
270
295
|
// allow it outside [0,1]
|
|
271
|
-
ax.domain = [
|
|
272
|
-
vFrac +
|
|
273
|
-
vFrac + lenFrac -
|
|
296
|
+
ax.domain = isVertical ? [
|
|
297
|
+
vFrac + ypad / gs.h,
|
|
298
|
+
vFrac + lenFrac - ypad / gs.h
|
|
299
|
+
] : [
|
|
300
|
+
vFrac + xpad / gs.w,
|
|
301
|
+
vFrac + lenFrac - xpad / gs.w
|
|
274
302
|
];
|
|
275
303
|
|
|
276
304
|
ax.setScale();
|
|
@@ -280,9 +308,13 @@ function drawColorBar(g, opts, gd) {
|
|
|
280
308
|
var titleCont = g.select('.' + cn.cbtitleunshift)
|
|
281
309
|
.attr('transform', strTranslate(-Math.round(gs.l), -Math.round(gs.t)));
|
|
282
310
|
|
|
311
|
+
var ticklabelposition = ax.ticklabelposition;
|
|
312
|
+
var titleFontSize = ax.title.font.size;
|
|
313
|
+
|
|
283
314
|
var axLayer = g.select('.' + cn.cbaxis);
|
|
284
315
|
var titleEl;
|
|
285
316
|
var titleHeight = 0;
|
|
317
|
+
var titleWidth = 0;
|
|
286
318
|
|
|
287
319
|
function drawTitle(titleClass, titleOpts) {
|
|
288
320
|
var dfltTitleOpts = {
|
|
@@ -307,54 +339,98 @@ function drawColorBar(g, opts, gd) {
|
|
|
307
339
|
}
|
|
308
340
|
|
|
309
341
|
function drawDummyTitle() {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
342
|
+
// draw the title so we know how much room it needs
|
|
343
|
+
// when we squish the axis.
|
|
344
|
+
// On vertical colorbars this only applies to top or bottom titles, not right side.
|
|
345
|
+
// On horizontal colorbars this only applies to right, etc.
|
|
346
|
+
|
|
347
|
+
if(
|
|
348
|
+
(isVertical && topOrBottom) ||
|
|
349
|
+
(!isVertical && !topOrBottom)
|
|
350
|
+
) {
|
|
351
|
+
var x, y;
|
|
317
352
|
|
|
318
353
|
if(titleSide === 'top') {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
|
|
354
|
+
x = xpad + gs.l + gs.w * optsX;
|
|
355
|
+
y = ypad + gs.t + gs.h * (1 - vFrac - lenFrac) + 3 + titleFontSize * 0.75;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if(titleSide === 'bottom') {
|
|
359
|
+
x = xpad + gs.l + gs.w * optsX;
|
|
360
|
+
y = ypad + gs.t + gs.h * (1 - vFrac) - 3 - titleFontSize * 0.25;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if(titleSide === 'right') {
|
|
364
|
+
y = ypad + gs.t + gs.h * optsY + 3 + titleFontSize * 0.75;
|
|
365
|
+
x = xpad + gs.l + gs.w * vFrac;
|
|
324
366
|
}
|
|
367
|
+
|
|
325
368
|
drawTitle(ax._id + 'title', {
|
|
326
|
-
attributes: {x: x, y: y, 'text-anchor': 'start'}
|
|
369
|
+
attributes: {x: x, y: y, 'text-anchor': isVertical ? 'start' : 'middle'}
|
|
327
370
|
});
|
|
328
371
|
}
|
|
329
372
|
}
|
|
330
373
|
|
|
331
374
|
function drawCbTitle() {
|
|
332
|
-
if(
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
375
|
+
if(
|
|
376
|
+
(isVertical && !topOrBottom) ||
|
|
377
|
+
(!isVertical && topOrBottom)
|
|
378
|
+
) {
|
|
379
|
+
var pos = ax.position || 0;
|
|
380
|
+
var mid = ax._offset + ax._length / 2;
|
|
381
|
+
var x, y;
|
|
382
|
+
|
|
383
|
+
if(titleSide === 'right') {
|
|
384
|
+
y = mid;
|
|
385
|
+
x = gs.l + gs.w * pos + 10 + titleFontSize * (
|
|
386
|
+
ax.showticklabels ? 1 : 0.5
|
|
387
|
+
);
|
|
388
|
+
} else {
|
|
389
|
+
x = mid;
|
|
390
|
+
|
|
391
|
+
if(titleSide === 'bottom') {
|
|
392
|
+
y = gs.t + gs.h * pos + 10 + (
|
|
393
|
+
ticklabelposition.indexOf('inside') === -1 ?
|
|
394
|
+
ax.tickfont.size :
|
|
395
|
+
0
|
|
396
|
+
) + (
|
|
397
|
+
ax.ticks !== 'intside' ?
|
|
398
|
+
opts.ticklen || 0 :
|
|
399
|
+
0
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if(titleSide === 'top') {
|
|
404
|
+
var nlines = title.text.split('<br>').length;
|
|
405
|
+
y = gs.t + gs.h * pos + 10 - thickPx - LINE_SPACING * titleFontSize * nlines;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
drawTitle((isVertical ?
|
|
410
|
+
// the 'h' + is a hack to get around the fact that
|
|
411
|
+
// convertToTspans rotates any 'y...' class by 90 degrees.
|
|
412
|
+
// TODO: find a better way to control this.
|
|
413
|
+
'h' :
|
|
414
|
+
'v'
|
|
415
|
+
) + ax._id + 'title', {
|
|
343
416
|
avoid: {
|
|
344
417
|
selection: d3.select(gd).selectAll('g.' + ax._id + 'tick'),
|
|
345
418
|
side: titleSide,
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
maxShift: fullLayout.width
|
|
419
|
+
offsetTop: isVertical ? 0 : gs.t,
|
|
420
|
+
offsetLeft: isVertical ? gs.l : 0,
|
|
421
|
+
maxShift: isVertical ? fullLayout.width : fullLayout.height
|
|
349
422
|
},
|
|
350
423
|
attributes: {x: x, y: y, 'text-anchor': 'middle'},
|
|
351
|
-
transform: {rotate:
|
|
424
|
+
transform: {rotate: isVertical ? -90 : 0, offset: 0}
|
|
352
425
|
});
|
|
353
426
|
}
|
|
354
427
|
}
|
|
355
428
|
|
|
356
429
|
function drawAxis() {
|
|
357
|
-
if(
|
|
430
|
+
if(
|
|
431
|
+
(!isVertical && !topOrBottom) ||
|
|
432
|
+
(isVertical && topOrBottom)
|
|
433
|
+
) {
|
|
358
434
|
// squish the axis top to make room for the title
|
|
359
435
|
var titleGroup = g.select('.' + cn.cbtitle);
|
|
360
436
|
var titleText = titleGroup.select('text');
|
|
@@ -366,39 +442,63 @@ function drawColorBar(g, opts, gd) {
|
|
|
366
442
|
if(titleText.node()) {
|
|
367
443
|
lineSize = parseInt(titleText.node().style.fontSize, 10) * LINE_SPACING;
|
|
368
444
|
}
|
|
445
|
+
|
|
446
|
+
var bb;
|
|
369
447
|
if(mathJaxNode) {
|
|
370
|
-
|
|
448
|
+
bb = Drawing.bBox(mathJaxNode);
|
|
449
|
+
titleWidth = bb.width;
|
|
450
|
+
titleHeight = bb.height;
|
|
371
451
|
if(titleHeight > lineSize) {
|
|
372
452
|
// not entirely sure how mathjax is doing
|
|
373
453
|
// vertical alignment, but this seems to work.
|
|
374
454
|
titleTrans[1] -= (titleHeight - lineSize) / 2;
|
|
375
455
|
}
|
|
376
456
|
} else if(titleText.node() && !titleText.classed(cn.jsPlaceholder)) {
|
|
377
|
-
|
|
457
|
+
bb = Drawing.bBox(titleText.node());
|
|
458
|
+
titleWidth = bb.width;
|
|
459
|
+
titleHeight = bb.height;
|
|
378
460
|
}
|
|
379
|
-
if(titleHeight) {
|
|
380
|
-
// buffer btwn colorbar and title
|
|
381
|
-
// TODO: configurable
|
|
382
|
-
titleHeight += 5;
|
|
383
461
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
462
|
+
if(isVertical) {
|
|
463
|
+
if(titleHeight) {
|
|
464
|
+
// buffer btwn colorbar and title
|
|
465
|
+
// TODO: configurable
|
|
466
|
+
titleHeight += 5;
|
|
467
|
+
|
|
468
|
+
if(titleSide === 'top') {
|
|
469
|
+
ax.domain[1] -= titleHeight / gs.h;
|
|
470
|
+
titleTrans[1] *= -1;
|
|
471
|
+
} else {
|
|
472
|
+
ax.domain[0] += titleHeight / gs.h;
|
|
473
|
+
var nlines = svgTextUtils.lineCount(titleText);
|
|
474
|
+
titleTrans[1] += (1 - nlines) * lineSize;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
titleGroup.attr('transform', strTranslate(titleTrans[0], titleTrans[1]));
|
|
478
|
+
ax.setScale();
|
|
479
|
+
}
|
|
480
|
+
} else { // horizontal colorbars
|
|
481
|
+
if(titleWidth) {
|
|
482
|
+
if(titleSide === 'right') {
|
|
483
|
+
ax.domain[0] += (titleWidth + titleFontSize / 2) / gs.w;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
titleGroup.attr('transform', strTranslate(titleTrans[0], titleTrans[1]));
|
|
487
|
+
ax.setScale();
|
|
391
488
|
}
|
|
392
|
-
|
|
393
|
-
titleGroup.attr('transform', strTranslate(titleTrans[0], titleTrans[1]));
|
|
394
|
-
ax.setScale();
|
|
395
489
|
}
|
|
396
490
|
}
|
|
397
491
|
|
|
398
492
|
g.selectAll('.' + cn.cbfills + ',.' + cn.cblines)
|
|
399
|
-
.attr('transform',
|
|
493
|
+
.attr('transform', isVertical ?
|
|
494
|
+
strTranslate(0, Math.round(gs.h * (1 - ax.domain[1]))) :
|
|
495
|
+
strTranslate(Math.round(gs.w * ax.domain[0]), 0)
|
|
496
|
+
);
|
|
400
497
|
|
|
401
|
-
axLayer.attr('transform',
|
|
498
|
+
axLayer.attr('transform', isVertical ?
|
|
499
|
+
strTranslate(0, Math.round(-gs.t)) :
|
|
500
|
+
strTranslate(Math.round(-gs.l), 0)
|
|
501
|
+
);
|
|
402
502
|
|
|
403
503
|
var fills = g.select('.' + cn.cbfills)
|
|
404
504
|
.selectAll('rect.' + cn.cbfill)
|
|
@@ -424,20 +524,22 @@ function drawColorBar(g, opts, gd) {
|
|
|
424
524
|
|
|
425
525
|
// offset the side adjoining the next rectangle so they
|
|
426
526
|
// overlap, to prevent antialiasing gaps
|
|
427
|
-
|
|
428
|
-
|
|
527
|
+
if(isVertical) {
|
|
528
|
+
z[1] = Lib.constrain(z[1] + (z[1] > z[0]) ? 1 : -1, zBounds[0], zBounds[1]);
|
|
529
|
+
} /* else {
|
|
530
|
+
// TODO: horizontal case
|
|
531
|
+
} */
|
|
429
532
|
|
|
430
533
|
// Colorbar cannot currently support opacities so we
|
|
431
534
|
// use an opaque fill even when alpha channels present
|
|
432
|
-
var fillEl = d3.select(this)
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
});
|
|
535
|
+
var fillEl = d3.select(this)
|
|
536
|
+
.attr(isVertical ? 'x' : 'y', uPx)
|
|
537
|
+
.attr(isVertical ? 'y' : 'x', d3.min(z))
|
|
538
|
+
.attr(isVertical ? 'width' : 'height', Math.max(thickPx, 2))
|
|
539
|
+
.attr(isVertical ? 'height' : 'width', Math.max(d3.max(z) - d3.min(z), 2));
|
|
438
540
|
|
|
439
541
|
if(opts._fillgradient) {
|
|
440
|
-
Drawing.gradient(fillEl, gd, opts._id, 'vertical', opts._fillgradient, 'fill');
|
|
542
|
+
Drawing.gradient(fillEl, gd, opts._id, isVertical ? 'vertical' : 'horizontalreversed', opts._fillgradient, 'fill');
|
|
441
543
|
} else {
|
|
442
544
|
// tinycolor can't handle exponents and
|
|
443
545
|
// at this scale, removing it makes no difference.
|
|
@@ -453,9 +555,15 @@ function drawColorBar(g, opts, gd) {
|
|
|
453
555
|
.classed(cn.cbline, true);
|
|
454
556
|
lines.exit().remove();
|
|
455
557
|
lines.each(function(d) {
|
|
558
|
+
var a = uPx;
|
|
559
|
+
var b = (Math.round(ax.c2p(d)) + (line.width / 2) % 1);
|
|
560
|
+
|
|
456
561
|
d3.select(this)
|
|
457
|
-
.attr('d', 'M' +
|
|
458
|
-
(
|
|
562
|
+
.attr('d', 'M' +
|
|
563
|
+
(isVertical ? a + ',' + b : b + ',' + a) +
|
|
564
|
+
(isVertical ? 'h' : 'v') +
|
|
565
|
+
thickPx
|
|
566
|
+
)
|
|
459
567
|
.call(Drawing.lineGroupStyle, line.width, lineColormap(d), line.dash);
|
|
460
568
|
});
|
|
461
569
|
|
|
@@ -488,82 +596,211 @@ function drawColorBar(g, opts, gd) {
|
|
|
488
596
|
// TODO: why are we redrawing multiple times now with this?
|
|
489
597
|
// I guess autoMargin doesn't like being post-promise?
|
|
490
598
|
function positionCB() {
|
|
599
|
+
var bb;
|
|
491
600
|
var innerThickness = thickPx + outlinewidth / 2;
|
|
492
|
-
if(
|
|
493
|
-
|
|
601
|
+
if(ticklabelposition.indexOf('inside') === -1) {
|
|
602
|
+
bb = Drawing.bBox(axLayer.node());
|
|
603
|
+
innerThickness += isVertical ? bb.width : bb.height;
|
|
494
604
|
}
|
|
495
605
|
|
|
496
606
|
titleEl = titleCont.select('text');
|
|
497
607
|
|
|
608
|
+
var titleWidth = 0;
|
|
609
|
+
|
|
610
|
+
var topSideVertical = isVertical && titleSide === 'top';
|
|
611
|
+
var rightSideHorizontal = !isVertical && titleSide === 'right';
|
|
612
|
+
|
|
613
|
+
var moveY = 0;
|
|
614
|
+
|
|
498
615
|
if(titleEl.node() && !titleEl.classed(cn.jsPlaceholder)) {
|
|
616
|
+
var _titleHeight;
|
|
617
|
+
|
|
499
618
|
var mathJaxNode = titleCont.select('.h' + ax._id + 'title-math-group').node();
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
619
|
+
if(mathJaxNode && (
|
|
620
|
+
(isVertical && topOrBottom) ||
|
|
621
|
+
(!isVertical && !topOrBottom)
|
|
622
|
+
)) {
|
|
623
|
+
bb = Drawing.bBox(mathJaxNode);
|
|
624
|
+
titleWidth = bb.width;
|
|
625
|
+
_titleHeight = bb.height;
|
|
503
626
|
} else {
|
|
504
627
|
// note: the formula below works for all title sides,
|
|
505
628
|
// (except for top/bottom mathjax, above)
|
|
506
629
|
// but the weird gs.l is because the titleunshift
|
|
507
630
|
// transform gets removed by Drawing.bBox
|
|
508
|
-
|
|
631
|
+
bb = Drawing.bBox(titleCont.node());
|
|
632
|
+
titleWidth = bb.right - gs.l - (isVertical ? uPx : vPx);
|
|
633
|
+
_titleHeight = bb.bottom - gs.t - (isVertical ? vPx : uPx);
|
|
634
|
+
|
|
635
|
+
if(
|
|
636
|
+
!isVertical && titleSide === 'top'
|
|
637
|
+
) {
|
|
638
|
+
innerThickness += bb.height;
|
|
639
|
+
moveY = bb.height;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
if(rightSideHorizontal) {
|
|
644
|
+
titleEl.attr('transform', strTranslate(titleWidth / 2 + titleFontSize / 2, 0));
|
|
645
|
+
|
|
646
|
+
titleWidth *= 2;
|
|
509
647
|
}
|
|
510
|
-
|
|
648
|
+
|
|
649
|
+
innerThickness = Math.max(innerThickness,
|
|
650
|
+
isVertical ? titleWidth : _titleHeight
|
|
651
|
+
);
|
|
511
652
|
}
|
|
512
653
|
|
|
513
|
-
var outerThickness =
|
|
654
|
+
var outerThickness = (isVertical ?
|
|
655
|
+
xpad :
|
|
656
|
+
ypad
|
|
657
|
+
) * 2 + innerThickness + borderwidth + outlinewidth / 2;
|
|
658
|
+
|
|
659
|
+
var hColorbarMoveTitle = 0;
|
|
660
|
+
if(!isVertical && title.text && yanchor === 'bottom' && optsY <= 0) {
|
|
661
|
+
hColorbarMoveTitle = outerThickness / 2;
|
|
662
|
+
|
|
663
|
+
outerThickness += hColorbarMoveTitle;
|
|
664
|
+
moveY += hColorbarMoveTitle;
|
|
665
|
+
}
|
|
666
|
+
fullLayout._hColorbarMoveTitle = hColorbarMoveTitle;
|
|
667
|
+
fullLayout._hColorbarMoveCBTitle = moveY;
|
|
514
668
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
.
|
|
669
|
+
var extraW = borderwidth + outlinewidth;
|
|
670
|
+
|
|
671
|
+
g.select('.' + cn.cbbg)
|
|
672
|
+
.attr('x', (isVertical ? uPx : vPx) - extraW / 2 - (isVertical ? xpad : 0))
|
|
673
|
+
.attr('y', (isVertical ? vPx : uPx) - (isVertical ? lenPx : ypad + moveY - hColorbarMoveTitle))
|
|
674
|
+
.attr(isVertical ? 'width' : 'height', Math.max(outerThickness - hColorbarMoveTitle, 2))
|
|
675
|
+
.attr(isVertical ? 'height' : 'width', Math.max(lenPx + extraW, 2))
|
|
676
|
+
.call(Color.fill, bgcolor)
|
|
522
677
|
.call(Color.stroke, opts.bordercolor)
|
|
523
678
|
.style('stroke-width', borderwidth);
|
|
524
679
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
680
|
+
var moveX = rightSideHorizontal ? Math.max(titleWidth - 10, 0) : 0;
|
|
681
|
+
|
|
682
|
+
g.selectAll('.' + cn.cboutline)
|
|
683
|
+
.attr('x', (isVertical ? uPx : vPx + xpad) + moveX)
|
|
684
|
+
.attr('y', (isVertical ? vPx + ypad - lenPx : uPx) + (topSideVertical ? titleHeight : 0))
|
|
685
|
+
.attr(isVertical ? 'width' : 'height', Math.max(thickPx, 2))
|
|
686
|
+
.attr(isVertical ? 'height' : 'width', Math.max(lenPx - (isVertical ?
|
|
687
|
+
2 * ypad + titleHeight :
|
|
688
|
+
2 * xpad + moveX
|
|
689
|
+
), 2))
|
|
531
690
|
.call(Color.stroke, opts.outlinecolor)
|
|
532
691
|
.style({
|
|
533
692
|
fill: 'none',
|
|
534
693
|
'stroke-width': outlinewidth
|
|
535
694
|
});
|
|
536
695
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
696
|
+
g.attr('transform', strTranslate(
|
|
697
|
+
gs.l - (isVertical ? xRatio * outerThickness : 0),
|
|
698
|
+
gs.t - (isVertical ? 0 : (1 - yRatio) * outerThickness - moveY)
|
|
699
|
+
));
|
|
700
|
+
|
|
701
|
+
if(!isVertical && (
|
|
702
|
+
borderwidth || (
|
|
703
|
+
tinycolor(bgcolor).getAlpha() &&
|
|
704
|
+
!tinycolor.equals(fullLayout.paper_bgcolor, bgcolor)
|
|
705
|
+
)
|
|
706
|
+
)) {
|
|
707
|
+
// for horizontal colorbars when there is a border line or having different background color
|
|
708
|
+
// hide/adjust x positioning for the first/last tick labels if they go outside the border
|
|
709
|
+
var tickLabels = axLayer.selectAll('text');
|
|
710
|
+
var numTicks = tickLabels[0].length;
|
|
711
|
+
|
|
712
|
+
var border = g.select('.' + cn.cbbg).node();
|
|
713
|
+
var oBb = Drawing.bBox(border);
|
|
714
|
+
var oTr = Drawing.getTranslate(g);
|
|
715
|
+
|
|
716
|
+
var TEXTPAD = 2;
|
|
717
|
+
|
|
718
|
+
tickLabels.each(function(d, i) {
|
|
719
|
+
var first = 0;
|
|
720
|
+
var last = numTicks - 1;
|
|
721
|
+
if(i === first || i === last) {
|
|
722
|
+
var iBb = Drawing.bBox(this);
|
|
723
|
+
var iTr = Drawing.getTranslate(this);
|
|
724
|
+
var deltaX;
|
|
725
|
+
|
|
726
|
+
if(i === last) {
|
|
727
|
+
var iRight = iBb.right + iTr.x;
|
|
728
|
+
var oRight = oBb.right + oTr.x + vPx - borderwidth - TEXTPAD + optsX;
|
|
729
|
+
|
|
730
|
+
deltaX = oRight - iRight;
|
|
731
|
+
if(deltaX > 0) deltaX = 0;
|
|
732
|
+
} else if(i === first) {
|
|
733
|
+
var iLeft = iBb.left + iTr.x;
|
|
734
|
+
var oLeft = oBb.left + oTr.x + vPx + borderwidth + TEXTPAD;
|
|
735
|
+
|
|
736
|
+
deltaX = oLeft - iLeft;
|
|
737
|
+
if(deltaX < 0) deltaX = 0;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
if(deltaX) {
|
|
741
|
+
if(numTicks < 3) { // adjust position
|
|
742
|
+
this.setAttribute('transform',
|
|
743
|
+
'translate(' + deltaX + ',0) ' +
|
|
744
|
+
this.getAttribute('transform')
|
|
745
|
+
);
|
|
746
|
+
} else { // hide
|
|
747
|
+
this.setAttribute('visibility', 'hidden');
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
});
|
|
752
|
+
}
|
|
540
753
|
|
|
541
754
|
// auto margin adjustment
|
|
542
755
|
var marginOpts = {};
|
|
756
|
+
var lFrac = FROM_TL[xanchor];
|
|
757
|
+
var rFrac = FROM_BR[xanchor];
|
|
543
758
|
var tFrac = FROM_TL[yanchor];
|
|
544
759
|
var bFrac = FROM_BR[yanchor];
|
|
545
|
-
if(lenmode === 'pixels') {
|
|
546
|
-
marginOpts.y = optsY;
|
|
547
|
-
marginOpts.t = lenPx * tFrac;
|
|
548
|
-
marginOpts.b = lenPx * bFrac;
|
|
549
|
-
} else {
|
|
550
|
-
marginOpts.t = marginOpts.b = 0;
|
|
551
|
-
marginOpts.yt = optsY + len * tFrac;
|
|
552
|
-
marginOpts.yb = optsY - len * bFrac;
|
|
553
|
-
}
|
|
554
760
|
|
|
555
|
-
var
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
761
|
+
var extraThickness = outerThickness - thickPx;
|
|
762
|
+
if(isVertical) {
|
|
763
|
+
if(lenmode === 'pixels') {
|
|
764
|
+
marginOpts.y = optsY;
|
|
765
|
+
marginOpts.t = lenPx * tFrac;
|
|
766
|
+
marginOpts.b = lenPx * bFrac;
|
|
767
|
+
} else {
|
|
768
|
+
marginOpts.t = marginOpts.b = 0;
|
|
769
|
+
marginOpts.yt = optsY + len * tFrac;
|
|
770
|
+
marginOpts.yb = optsY - len * bFrac;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
if(thicknessmode === 'pixels') {
|
|
774
|
+
marginOpts.x = optsX;
|
|
775
|
+
marginOpts.l = outerThickness * lFrac;
|
|
776
|
+
marginOpts.r = outerThickness * rFrac;
|
|
777
|
+
} else {
|
|
778
|
+
marginOpts.l = extraThickness * lFrac;
|
|
779
|
+
marginOpts.r = extraThickness * rFrac;
|
|
780
|
+
marginOpts.xl = optsX - thickness * lFrac;
|
|
781
|
+
marginOpts.xr = optsX + thickness * rFrac;
|
|
782
|
+
}
|
|
783
|
+
} else { // horizontal colorbars
|
|
784
|
+
if(lenmode === 'pixels') {
|
|
785
|
+
marginOpts.x = optsX;
|
|
786
|
+
marginOpts.l = lenPx * lFrac;
|
|
787
|
+
marginOpts.r = lenPx * rFrac;
|
|
788
|
+
} else {
|
|
789
|
+
marginOpts.l = marginOpts.r = 0;
|
|
790
|
+
marginOpts.xl = optsX + len * lFrac;
|
|
791
|
+
marginOpts.xr = optsX - len * rFrac;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
if(thicknessmode === 'pixels') {
|
|
795
|
+
marginOpts.y = 1 - optsY;
|
|
796
|
+
marginOpts.t = outerThickness * tFrac;
|
|
797
|
+
marginOpts.b = outerThickness * bFrac;
|
|
798
|
+
} else {
|
|
799
|
+
marginOpts.t = extraThickness * tFrac;
|
|
800
|
+
marginOpts.b = extraThickness * bFrac;
|
|
801
|
+
marginOpts.yt = optsY - thickness * tFrac;
|
|
802
|
+
marginOpts.yb = optsY + thickness * bFrac;
|
|
803
|
+
}
|
|
567
804
|
}
|
|
568
805
|
|
|
569
806
|
Plots.autoMargin(gd, opts._id, marginOpts);
|
|
@@ -580,6 +817,7 @@ function drawColorBar(g, opts, gd) {
|
|
|
580
817
|
}
|
|
581
818
|
|
|
582
819
|
function makeEditable(g, opts, gd) {
|
|
820
|
+
var isVertical = opts.orientation === 'v';
|
|
583
821
|
var fullLayout = gd._fullLayout;
|
|
584
822
|
var gs = fullLayout._size;
|
|
585
823
|
var t0, xf, yf;
|
|
@@ -594,9 +832,13 @@ function makeEditable(g, opts, gd) {
|
|
|
594
832
|
moveFn: function(dx, dy) {
|
|
595
833
|
g.attr('transform', t0 + strTranslate(dx, dy));
|
|
596
834
|
|
|
597
|
-
xf = dragElement.align(
|
|
835
|
+
xf = dragElement.align(
|
|
836
|
+
(isVertical ? opts._uFrac : opts._vFrac) + (dx / gs.w),
|
|
837
|
+
isVertical ? opts._thickFrac : opts._lenFrac,
|
|
598
838
|
0, 1, opts.xanchor);
|
|
599
|
-
yf = dragElement.align(
|
|
839
|
+
yf = dragElement.align(
|
|
840
|
+
(isVertical ? opts._vFrac : (1 - opts._uFrac)) - (dy / gs.h),
|
|
841
|
+
isVertical ? opts._lenFrac : opts._thickFrac,
|
|
600
842
|
0, 1, opts.yanchor);
|
|
601
843
|
|
|
602
844
|
var csr = dragElement.getCursor(xf, yf, opts.xanchor, opts.yanchor);
|
|
@@ -673,6 +915,8 @@ function calcLevels(gd, opts, zrange) {
|
|
|
673
915
|
function mockColorBarAxis(gd, opts, zrange) {
|
|
674
916
|
var fullLayout = gd._fullLayout;
|
|
675
917
|
|
|
918
|
+
var isVertical = opts.orientation === 'v';
|
|
919
|
+
|
|
676
920
|
var cbAxisIn = {
|
|
677
921
|
type: 'linear',
|
|
678
922
|
range: zrange,
|
|
@@ -703,17 +947,19 @@ function mockColorBarAxis(gd, opts, zrange) {
|
|
|
703
947
|
title: opts.title,
|
|
704
948
|
showline: true,
|
|
705
949
|
anchor: 'free',
|
|
706
|
-
side: 'right',
|
|
950
|
+
side: isVertical ? 'right' : 'bottom',
|
|
707
951
|
position: 1
|
|
708
952
|
};
|
|
709
953
|
|
|
954
|
+
var letter = isVertical ? 'y' : 'x';
|
|
955
|
+
|
|
710
956
|
var cbAxisOut = {
|
|
711
957
|
type: 'linear',
|
|
712
|
-
_id:
|
|
958
|
+
_id: letter + opts._id
|
|
713
959
|
};
|
|
714
960
|
|
|
715
961
|
var axisOptions = {
|
|
716
|
-
letter:
|
|
962
|
+
letter: letter,
|
|
717
963
|
font: fullLayout.font,
|
|
718
964
|
noHover: true,
|
|
719
965
|
noTickson: true,
|