@@ -15,6 +15,8 @@ var map1dArray = require('./map_1d_array');
1515var makepath = require ( './makepath' ) ;
1616var orientText = require ( './orient_text' ) ;
1717var svgTextUtils = require ( '../../lib/svg_text_utils' ) ;
18+ var Lib = require ( '../../lib' ) ;
19+ var alignmentConstants = require ( '../../constants/alignment' ) ;
1820
1921module . exports = function plot ( gd , plotinfo , cdcarpet ) {
2022 for ( var i = 0 ; i < cdcarpet . length ; i ++ ) {
@@ -58,10 +60,10 @@ function plotOne(gd, plotinfo, cd) {
5860 drawGridLines ( xa , ya , boundaryLayer , aax , 'a-boundary' , aax . _boundarylines ) ;
5961 drawGridLines ( xa , ya , boundaryLayer , bax , 'b-boundary' , bax . _boundarylines ) ;
6062
61- var maxAExtent = drawAxisLabels ( gd , xa , ya , trace , t , labelLayer , aax . _labels , 'a-label' ) ;
62- var maxBExtent = drawAxisLabels ( gd , xa , ya , trace , t , labelLayer , bax . _labels , 'b-label' ) ;
63+ var labelOrientationA = drawAxisLabels ( gd , xa , ya , trace , t , labelLayer , aax . _labels , 'a-label' ) ;
64+ var labelOrientationB = drawAxisLabels ( gd , xa , ya , trace , t , labelLayer , bax . _labels , 'b-label' ) ;
6365
64- drawAxisTitles ( gd , labelLayer , trace , t , xa , ya , maxAExtent , maxBExtent ) ;
66+ drawAxisTitles ( gd , labelLayer , trace , t , xa , ya , labelOrientationA , labelOrientationB ) ;
6567
6668 drawClipPath ( trace , t , clipLayer , xa , ya ) ;
6769}
@@ -131,8 +133,9 @@ function drawAxisLabels(gd, xaxis, yaxis, trace, t, layer, labels, labelClass) {
131133 . classed ( labelClass , true ) ;
132134
133135 var maxExtent = 0 ;
136+ var labelOrientation = { } ;
134137
135- labelJoin . each ( function ( label ) {
138+ labelJoin . each ( function ( label , i ) {
136139 // Most of the positioning is done in calc_labels. Only the parts that depend upon
137140 // the screen space representation of the x and y axes are here:
138141 var orientation ;
@@ -142,6 +145,11 @@ function drawAxisLabels(gd, xaxis, yaxis, trace, t, layer, labels, labelClass) {
142145 var angle = ( label . axis . tickangle + 180.0 ) * Math . PI / 180.0 ;
143146 orientation = orientText ( trace , xaxis , yaxis , label . xy , [ Math . cos ( angle ) , Math . sin ( angle ) ] ) ;
144147 }
148+
149+ if ( ! i ) {
150+ // TODO: offsetMultiplier? Not currently used anywhere...
151+ labelOrientation = { angle : orientation . angle , flip : orientation . flip } ;
152+ }
145153 var direction = ( label . endAnchor ? - 1 : 1 ) * orientation . flip ;
146154
147155 var labelEl = d3 . select ( this )
@@ -169,29 +177,40 @@ function drawAxisLabels(gd, xaxis, yaxis, trace, t, layer, labels, labelClass) {
169177
170178 labelJoin . exit ( ) . remove ( ) ;
171179
172- return maxExtent ;
180+ labelOrientation . maxExtent = maxExtent ;
181+ return labelOrientation ;
173182}
174183
175- function drawAxisTitles ( gd , layer , trace , t , xa , ya , maxAExtent , maxBExtent ) {
184+ function drawAxisTitles ( gd , layer , trace , t , xa , ya , labelOrientationA , labelOrientationB ) {
176185 var a , b , xy , dxy ;
177186
178187 a = 0.5 * ( trace . a [ 0 ] + trace . a [ trace . a . length - 1 ] ) ;
179188 b = trace . b [ 0 ] ;
180189 xy = trace . ab2xy ( a , b , true ) ;
181190 dxy = trace . dxyda_rough ( a , b ) ;
182- drawAxisTitle ( gd , layer , trace , t , xy , dxy , trace . aaxis , xa , ya , maxAExtent , 'a-title' ) ;
191+ if ( labelOrientationA . angle === undefined ) {
192+ Lib . extendFlat ( labelOrientationA , orientText ( trace , xa , ya , xy , trace . dxydb_rough ( a , b ) ) ) ;
193+ }
194+ drawAxisTitle ( gd , layer , trace , t , xy , dxy , trace . aaxis , xa , ya , labelOrientationA , 'a-title' ) ;
183195
184196 a = trace . a [ 0 ] ;
185197 b = 0.5 * ( trace . b [ 0 ] + trace . b [ trace . b . length - 1 ] ) ;
186198 xy = trace . ab2xy ( a , b , true ) ;
187199 dxy = trace . dxydb_rough ( a , b ) ;
188- drawAxisTitle ( gd , layer , trace , t , xy , dxy , trace . baxis , xa , ya , maxBExtent , 'b-title' ) ;
200+ if ( labelOrientationB . angle === undefined ) {
201+ Lib . extendFlat ( labelOrientationB , orientText ( trace , xa , ya , xy , trace . dxyda_rough ( a , b ) ) ) ;
202+ }
203+ drawAxisTitle ( gd , layer , trace , t , xy , dxy , trace . baxis , xa , ya , labelOrientationB , 'b-title' ) ;
189204}
190205
191- function drawAxisTitle ( gd , layer , trace , t , xy , dxy , axis , xa , ya , offset , labelClass ) {
206+ var lineSpacing = alignmentConstants . LINE_SPACING ;
207+ var midShift = ( ( 1 - alignmentConstants . MID_SHIFT ) / lineSpacing ) + 1 ;
208+
209+ function drawAxisTitle ( gd , layer , trace , t , xy , dxy , axis , xa , ya , labelOrientation , labelClass ) {
192210 var data = [ ] ;
193211 if ( axis . title ) data . push ( axis . title ) ;
194212 var titleJoin = layer . selectAll ( 'text.' + labelClass ) . data ( data ) ;
213+ var offset = labelOrientation . maxExtent ;
195214
196215 titleJoin . enter ( ) . append ( 'text' )
197216 . classed ( labelClass , true ) ;
@@ -205,14 +224,23 @@ function drawAxisTitle(gd, layer, trace, t, xy, dxy, axis, xa, ya, offset, label
205224 }
206225
207226 // In addition to the size of the labels, add on some extra padding:
208- offset += axis . titlefont . size + axis . titleoffset ;
227+ var titleSize = axis . titlefont . size ;
228+ offset += titleSize + axis . titleoffset ;
209229
230+ var labelNorm = labelOrientation . angle + ( labelOrientation . flip < 0 ? 180 : 0 ) ;
231+ var angleDiff = ( labelNorm - orientation . angle + 450 ) % 360 ;
232+ var reverseTitle = angleDiff > 90 && angleDiff < 270 ;
210233
211234 var el = d3 . select ( this ) ;
212235
213236 el . text ( axis . title || '' )
214- . call ( svgTextUtils . convertToTspans , gd )
215- . attr ( 'transform' ,
237+ . call ( svgTextUtils . convertToTspans , gd ) ;
238+
239+ if ( reverseTitle ) {
240+ offset = ( - svgTextUtils . lineCount ( el ) + midShift ) * lineSpacing * titleSize - offset ;
241+ }
242+
243+ el . attr ( 'transform' ,
216244 'translate(' + orientation . p [ 0 ] + ',' + orientation . p [ 1 ] + ') ' +
217245 'rotate(' + orientation . angle + ') ' +
218246 'translate(0,' + offset + ')'
0 commit comments