Skip to content

Commit 9bbe295

Browse files
authored
Merge pull request #3326 from plotly/multicategory-inside-ticks
Multicategory inside ticks fixes
2 parents e1ac60b + c88c167 commit 9bbe295

File tree

7 files changed

+142
-7
lines changed

7 files changed

+142
-7
lines changed

src/plots/cartesian/axes.js

+7-7
Original file line numberDiff line numberDiff line change
@@ -1584,10 +1584,8 @@ axes.draw = function(gd, arg, opts) {
15841584

15851585
plotinfo.xaxislayer.selectAll('.' + xa._id + 'tick').remove();
15861586
plotinfo.yaxislayer.selectAll('.' + ya._id + 'tick').remove();
1587-
if(xa.type === 'multicategory') {
1588-
plotinfo.xaxislayer.selectAll('.' + xa._id + 'tick2').remove();
1589-
plotinfo.xaxislayer.selectAll('.' + xa._id + 'divider').remove();
1590-
}
1587+
plotinfo.xaxislayer.selectAll('.' + xa._id + 'tick2').remove();
1588+
plotinfo.xaxislayer.selectAll('.' + xa._id + 'divider').remove();
15911589
if(plotinfo.gridlayer) plotinfo.gridlayer.selectAll('path').remove();
15921590
if(plotinfo.zerolinelayer) plotinfo.zerolinelayer.selectAll('path').remove();
15931591
fullLayout._infolayer.select('.g-' + xa._id + 'title').remove();
@@ -1781,11 +1779,12 @@ axes.drawOne = function(gd, ax, opts) {
17811779
if(ax.type === 'multicategory') {
17821780
var labelLength = 0;
17831781
var pad = {x: 2, y: 10}[axLetter];
1782+
var sgn = tickSigns[2] * (ax.ticks === 'inside' ? -1 : 1);
17841783

17851784
seq.push(function() {
17861785
labelLength += getLabelLevelSpan(ax, axId + 'tick') + pad;
17871786
labelLength += ax._tickAngles[axId + 'tick'] ? ax.tickfont.size * LINE_SPACING : 0;
1788-
var secondaryPosition = mainLinePosition + labelLength * tickSigns[2];
1787+
var secondaryPosition = mainLinePosition + labelLength * sgn;
17891788
var secondaryLabelFns = axes.makeLabelFns(ax, secondaryPosition);
17901789

17911790
return axes.drawLabels(gd, ax, {
@@ -1803,11 +1802,12 @@ axes.drawOne = function(gd, ax, opts) {
18031802

18041803
seq.push(function() {
18051804
labelLength += getLabelLevelSpan(ax, axId + 'tick2');
1805+
ax._labelLength = labelLength;
18061806

18071807
return drawDividers(gd, ax, {
18081808
vals: dividerVals,
18091809
layer: mainAxLayer,
1810-
path: axes.makeTickPath(ax, mainLinePosition, tickSigns[2], labelLength),
1810+
path: axes.makeTickPath(ax, mainLinePosition, sgn, labelLength),
18111811
transFn: transFn
18121812
});
18131813
});
@@ -2608,7 +2608,7 @@ function drawTitle(gd, ax) {
26082608

26092609
var titleStandoff;
26102610
if(ax.type === 'multicategory') {
2611-
titleStandoff = ax._boundingBox[{x: 'height', y: 'width'}[axLetter]];
2611+
titleStandoff = ax._labelLength;
26122612
} else {
26132613
var offsetBase = 1.5;
26142614
titleStandoff = 10 + fontSize * offsetBase + (ax.linewidth ? ax.linewidth - 1 : 0);
Loading
1.88 KB
Loading
-2 Bytes
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{
2+
"data": [
3+
{
4+
"type": "bar",
5+
"x": [
6+
["2017", "2017", "2017", "2017", "2018", "2018", "2018"],
7+
["q1", "q2", "q3", "q4", "q1", "q2", "q3" ]
8+
],
9+
"y": [1, 2, 3, 1, 3, 2, 3, 1]
10+
},
11+
{
12+
"type": "bar",
13+
"x": [
14+
["2017", "2017", "2017", "2017", "2018", "2018", "2018"],
15+
["q1", "q2", "q3", "q4", "q1", "q2", "q3"]
16+
],
17+
"y": [1.12, 2.15, 3.07, 1.48, 2.78, 1.95, 2.54, 0.64]
18+
},
19+
20+
{
21+
"type": "bar",
22+
"x": [
23+
["2017", "2017", "2017", "2017", "2018", "2018", "2018"],
24+
["q1", "q2", "q3", "q4", "q1", "q2", "q3"]
25+
],
26+
"y": [1.12, 2.15, 3.07, 1.48, 2.78, 1.95, 2.54, 0.64],
27+
"xaxis": "x2",
28+
"yaxis": "y2"
29+
},
30+
{
31+
"type": "bar",
32+
"x": [
33+
["2017", "2017", "2017", "2017", "2018", "2018", "2018"],
34+
["q1", "q2", "q3", "q4", "q1", "q2", "q3" ]
35+
],
36+
"y": [1, 2, 3, 1, 3, 2, 3, 1],
37+
"xaxis": "x2",
38+
"yaxis": "y2"
39+
}
40+
],
41+
"layout": {
42+
"grid": {"rows": 2, "columns": 1, "pattern": "independent"},
43+
"xaxis": {
44+
"side": "top",
45+
"title": "MULTI-CATEGORY",
46+
"range": [-0.5, 7],
47+
"showline": true,
48+
"tickfont": {"size": 16},
49+
"ticks": "inside",
50+
"ticklen": 10,
51+
"tickcolor": "red",
52+
"tickwidth": 2,
53+
"dividercolor": "blue",
54+
"dividerwidth": 2
55+
},
56+
"xaxis2": {
57+
"title": "MULTI-CATEGORY",
58+
"range": [-1, 6.5],
59+
"showline": true,
60+
"tickfont": {"size": 16},
61+
"ticks": "inside",
62+
"ticklen": 10,
63+
"tickcolor": "red",
64+
"tickwidth": 2,
65+
"dividercolor": "blue",
66+
"dividerwidth": 2
67+
},
68+
"yaxis": {
69+
"zeroline": false
70+
},
71+
"yaxis2": {
72+
"zeroline": false
73+
},
74+
"showlegend": false
75+
}
76+
}

test/image/mocks/multicategory-mirror.json

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
],
2020
"layout": {
2121
"xaxis": {
22+
"title": "MULTI-CATEGORY",
2223
"ticks": "outside",
2324
"showline": true,
2425
"mirror": "ticks",

test/jasmine/tests/cartesian_test.js

+58
Original file line numberDiff line numberDiff line change
@@ -849,4 +849,62 @@ describe('subplot creation / deletion:', function() {
849849
.catch(failTest)
850850
.then(done);
851851
});
852+
853+
it('clears secondary labels and divider when updating out of axis type multicategory', function(done) {
854+
function _assert(msg, exp) {
855+
var gd3 = d3.select(gd);
856+
expect(gd3.selectAll('.xtick > text').size())
857+
.toBe(exp.tickCnt, msg + ' # labels');
858+
expect(gd3.selectAll('.xtick2 > text').size())
859+
.toBe(exp.tick2Cnt, msg + ' # secondary labels');
860+
expect(gd3.selectAll('.xdivider').size())
861+
.toBe(exp.dividerCnt, msg + ' # dividers');
862+
}
863+
864+
Plotly.react(gd, [{
865+
type: 'bar',
866+
x: ['a', 'b', 'c'],
867+
y: [1, 2, 1]
868+
}])
869+
.then(function() {
870+
_assert('base - category axis', {
871+
tickCnt: 3,
872+
tick2Cnt: 0,
873+
dividerCnt: 0
874+
});
875+
})
876+
.then(function() {
877+
return Plotly.react(gd, [{
878+
type: 'bar',
879+
x: [
880+
['d', 'd', 'e'],
881+
['a', 'b', 'c']
882+
],
883+
y: [1, 2, 3]
884+
}]);
885+
})
886+
.then(function() {
887+
_assert('multicategory axis', {
888+
tickCnt: 3,
889+
tick2Cnt: 2,
890+
dividerCnt: 3
891+
});
892+
})
893+
.then(function() {
894+
return Plotly.react(gd, [{
895+
type: 'bar',
896+
x: ['a', 'b', 'c'],
897+
y: [1, 2, 1]
898+
}]);
899+
})
900+
.then(function() {
901+
_assert('back to category axis', {
902+
tickCnt: 3,
903+
tick2Cnt: 0,
904+
dividerCnt: 0
905+
});
906+
})
907+
.catch(failTest)
908+
.then(done);
909+
});
852910
});

0 commit comments

Comments
 (0)