Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0857b44

Browse files
committed
refactor ugly logic out of Titles.draw
1 parent 637a956 commit 0857b44

File tree

4 files changed

+216
-177
lines changed

4 files changed

+216
-177
lines changed

src/components/colorbar/draw.js

Lines changed: 110 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ var Plots = require('../../plots/plots');
1616
var Axes = require('../../plots/cartesian/axes');
1717
var dragElement = require('../dragelement');
1818
var Lib = require('../../lib');
19+
var extendFlat = require('../../lib/extend').extendFlat;
1920
var setCursor = require('../../lib/setcursor');
2021
var Drawing = require('../drawing');
2122
var Color = require('../color');
@@ -52,7 +53,8 @@ module.exports = function draw(gd, id) {
5253
opts.filllevels = null;
5354

5455
function component() {
55-
var fullLayout = gd._fullLayout;
56+
var fullLayout = gd._fullLayout,
57+
gs = fullLayout._size;
5658
if((typeof opts.fillcolor !== 'function') &&
5759
(typeof opts.line.color !== 'function')) {
5860
fullLayout._infolayer.selectAll('g.'+id).remove();
@@ -116,25 +118,25 @@ module.exports = function draw(gd, id) {
116118
originalPlotWidth = fullLayout.width - fullLayout.margin.l - fullLayout.margin.r,
117119
thickPx = Math.round(opts.thickness *
118120
(opts.thicknessmode==='fraction' ? originalPlotWidth : 1)),
119-
thickFrac = thickPx / fullLayout._size.w,
121+
thickFrac = thickPx / gs.w,
120122
lenPx = Math.round(opts.len *
121123
(opts.lenmode==='fraction' ? originalPlotHeight : 1)),
122-
lenFrac = lenPx / fullLayout._size.h,
123-
xpadFrac = opts.xpad/fullLayout._size.w,
124+
lenFrac = lenPx / gs.h,
125+
xpadFrac = opts.xpad/gs.w,
124126
yExtraPx = (opts.borderwidth + opts.outlinewidth)/2,
125-
ypadFrac = opts.ypad / fullLayout._size.h,
127+
ypadFrac = opts.ypad / gs.h,
126128

127129
// x positioning: do it initially just for left anchor,
128130
// then fix at the end (since we don't know the width yet)
129-
xLeft = Math.round(opts.x*fullLayout._size.w + opts.xpad),
131+
xLeft = Math.round(opts.x*gs.w + opts.xpad),
130132
// for dragging... this is getting a little muddled...
131133
xLeftFrac = opts.x - thickFrac *
132134
({middle: 0.5, right: 1}[opts.xanchor]||0),
133135

134136
// y positioning we can do correctly from the start
135137
yBottomFrac = opts.y + lenFrac *
136138
(({top: -0.5, bottom: 0.5}[opts.yanchor] || 0) - 0.5),
137-
yBottomPx = Math.round(fullLayout._size.h * (1-yBottomFrac)),
139+
yBottomPx = Math.round(gs.h * (1-yBottomFrac)),
138140
yTopPx = yBottomPx-lenPx,
139141
titleEl,
140142
cbAxisIn = {
@@ -243,22 +245,38 @@ module.exports = function draw(gd, id) {
243245
s.append('g').classed('cbtitleunshift',true)
244246
.append('g').classed('cbtitle',true);
245247
s.append('rect').classed('cboutline',true);
248+
s.select('.cbtitle').datum(0);
246249
});
247-
container.attr('transform','translate('+Math.round(fullLayout._size.l)+
248-
','+Math.round(fullLayout._size.t)+')');
250+
container.attr('transform','translate('+Math.round(gs.l)+
251+
','+Math.round(gs.t)+')');
249252
// TODO: this opposite transform is a hack until we make it
250253
// more rational which items get this offset
251254
var titleCont = container.select('.cbtitleunshift')
252255
.attr('transform', 'translate(-'+
253-
Math.round(fullLayout._size.l) + ',-' +
254-
Math.round(fullLayout._size.t) + ')');
256+
Math.round(gs.l) + ',-' +
257+
Math.round(gs.t) + ')');
255258

256259
cbAxisOut._axislayer = container.select('.cbaxis');
257260
var titleHeight = 0;
258261
if(['top', 'bottom'].indexOf(opts.titleside) !== -1) {
259262
// draw the title so we know how much room it needs
260-
// when we squish the axis
261-
Titles.draw(gd, cbAxisOut._id + 'title');
263+
// when we squish the axis. This one only applies to
264+
// top or bottom titles, not right side.
265+
var x = gs.l + (opts.x + xpadFrac) * gs.w,
266+
fontSize = cbAxisOut.titlefont.size,
267+
y;
268+
269+
if(opts.titleside === 'top') {
270+
y = (1 - (yBottomFrac + lenFrac - ypadFrac)) * gs.h +
271+
gs.t + 3 + fontSize * 0.75;
272+
}
273+
else {
274+
y = (1 - (yBottomFrac + ypadFrac)) * gs.h +
275+
gs.t - 3 - fontSize * 0.25;
276+
}
277+
drawTitle(cbAxisOut._id + 'title', {
278+
attributes: {x: x, y: y, 'text-anchor': 'start'}
279+
});
262280
}
263281

264282
function drawAxis() {
@@ -295,11 +313,11 @@ module.exports = function draw(gd, id) {
295313
titleHeight += 5;
296314

297315
if(opts.titleside==='top') {
298-
cbAxisOut.domain[1] -= titleHeight/fullLayout._size.h;
316+
cbAxisOut.domain[1] -= titleHeight/gs.h;
299317
titleTrans[1] *= -1;
300318
}
301319
else {
302-
cbAxisOut.domain[0] += titleHeight/fullLayout._size.h;
320+
cbAxisOut.domain[0] += titleHeight/gs.h;
303321
var nlines = Math.max(1,
304322
titleText.selectAll('tspan.line').size());
305323
titleTrans[1] += (1-nlines)*lineSize;
@@ -314,7 +332,7 @@ module.exports = function draw(gd, id) {
314332

315333
container.selectAll('.cbfills,.cblines,.cbaxis')
316334
.attr('transform','translate(0,'+
317-
Math.round(fullLayout._size.h*(1-cbAxisOut.domain[1]))+')');
335+
Math.round(gs.h*(1-cbAxisOut.domain[1]))+')');
318336

319337
var fills = container.select('.cbfills')
320338
.selectAll('rect.cbfill')
@@ -371,7 +389,67 @@ module.exports = function draw(gd, id) {
371389
(opts.outlinewidth||0)/2 - (opts.ticks==='outside' ? 1 : 0);
372390
cbAxisOut.side = 'right';
373391

374-
return Axes.doTicks(gd, cbAxisOut);
392+
// separate out axis and title drawing,
393+
// so we don't need such complicated logic in Titles.draw
394+
// if title is on the top or bottom, we've already drawn it
395+
// this title call only handles side=right
396+
return Lib.syncOrAsync([
397+
function() {
398+
return Axes.doTicks(gd, cbAxisOut, true);
399+
},
400+
function() {
401+
if(['top','bottom'].indexOf(opts.titleside)===-1) {
402+
var fontSize = cbAxisOut.titlefont.size,
403+
y = cbAxisOut._offset + cbAxisOut._length / 2,
404+
x = gs.l + (cbAxisOut.position || 0) * gs.w + ((cbAxisOut.side === 'right') ?
405+
10 + fontSize*((cbAxisOut.showticklabels ? 1 : 0.5)) :
406+
-10 - fontSize*((cbAxisOut.showticklabels ? 0.5 : 0)));
407+
408+
// the 'h' + is a hack to get around the fact that
409+
// convertToTspans rotates any 'y...' class by 90 degrees.
410+
// TODO: find a better way to control this.
411+
drawTitle('h' + cbAxisOut._id + 'title', {
412+
avoid: {
413+
selection: d3.select(gd).selectAll('g.' + cbAxisOut._id + 'tick'),
414+
side: opts.titleside,
415+
offsetLeft: gs.l,
416+
offsetTop: gs.t,
417+
maxShift: fullLayout.width
418+
},
419+
attributes: {x: x, y: y, 'text-anchor': 'middle'},
420+
transform: {rotate: '-90', offset: 0}
421+
});
422+
}
423+
}]);
424+
}
425+
426+
function drawTitle(titleClass, titleOpts) {
427+
var trace = getTrace(),
428+
propName;
429+
if(Plots.traceIs(trace, 'markerColorscale')) {
430+
propName = 'marker.colorbar.title';
431+
}
432+
else propName = 'colorbar.title';
433+
434+
var dfltTitleOpts = {
435+
propContainer: cbAxisOut,
436+
propName: propName,
437+
traceIndex: trace.index,
438+
dfltName: 'colorscale',
439+
containerGroup: container.select('.cbtitle')
440+
};
441+
442+
// this class-to-rotate thing with convertToTspans is
443+
// getting hackier and hackier... delete groups with the
444+
// wrong class (in case earlier the colorbar was drawn on
445+
// a different side, I think?)
446+
var otherClass = titleClass.charAt(0) === 'h' ?
447+
titleClass.substr(1) : ('h' + titleClass);
448+
container.selectAll('.' + otherClass + ',.' + otherClass + '-math-group')
449+
.remove();
450+
451+
Titles.draw(gd, titleClass,
452+
extendFlat(dfltTitleOpts, titleOpts || {}));
375453
}
376454

377455
function positionCB() {
@@ -394,11 +472,11 @@ module.exports = function draw(gd, id) {
394472
else {
395473
// note: the formula below works for all titlesides,
396474
// (except for top/bottom mathjax, above)
397-
// but the weird fullLayout._size.l is because the titleunshift
475+
// but the weird gs.l is because the titleunshift
398476
// transform gets removed by Drawing.bBox
399477
titleWidth =
400478
Drawing.bBox(titleCont.node()).right -
401-
xLeft - fullLayout._size.l;
479+
xLeft - gs.l;
402480
}
403481
innerWidth = Math.max(innerWidth,titleWidth);
404482
}
@@ -435,7 +513,7 @@ module.exports = function draw(gd, id) {
435513
var xoffset = ({center: 0.5, right: 1}[opts.xanchor] || 0) *
436514
outerwidth;
437515
container.attr('transform',
438-
'translate('+(fullLayout._size.l-xoffset)+','+fullLayout._size.t+')');
516+
'translate('+(gs.l-xoffset)+','+gs.t+')');
439517

440518
//auto margin adjustment
441519
Plots.autoMargin(gd, id,{
@@ -470,8 +548,6 @@ module.exports = function draw(gd, id) {
470548
setCursor(container);
471549
},
472550
moveFn: function(dx, dy) {
473-
var gs = gd._fullLayout._size;
474-
475551
container.attr('transform',
476552
t0+' ' + 'translate('+dx+','+dy+')');
477553

@@ -480,33 +556,34 @@ module.exports = function draw(gd, id) {
480556
yf = dragElement.align(yBottomFrac - (dy/gs.h), lenFrac,
481557
0, 1, opts.yanchor);
482558

483-
var csr = dragElement.cursor(xf, yf,
559+
var csr = dragElement.getCursor(xf, yf,
484560
opts.xanchor, opts.yanchor);
485561
setCursor(container, csr);
486562
},
487563
doneFn: function(dragged) {
488564
setCursor(container);
489565

490566
if(dragged && xf!==undefined && yf!==undefined) {
491-
var idNum = id.substr(2),
492-
traceNum;
493-
gd._fullData.some(function(trace) {
494-
if(trace.uid===idNum) {
495-
traceNum = trace.index;
496-
return true;
497-
}
498-
});
499-
500567
Plotly.restyle(gd,
501568
{'colorbar.x': xf, 'colorbar.y': yf},
502-
traceNum);
569+
getTrace().index);
503570
}
504571
}
505572
});
506573
}
507574
return cbDone;
508575
}
509576

577+
function getTrace() {
578+
var idNum = id.substr(2),
579+
i,
580+
trace;
581+
for(i = 0; i < gd._fullData.length; i++) {
582+
trace = gd._fullData[i];
583+
if(trace.uid === idNum) return trace;
584+
}
585+
}
586+
510587
// setter/getters for every item defined in opts
511588
Object.keys(opts).forEach(function(name) {
512589
component[name] = function(v) {

0 commit comments

Comments
 (0)