@@ -1373,12 +1373,19 @@ axes.doTicks = function(td, axid, skipTitle) {
13731373 pad = ( ax . linewidth || 1 ) / 2 ,
13741374 labelStandoff =
13751375 ( ax . ticks === 'outside' ? ax . ticklen : 1 ) + ( ax . linewidth || 0 ) ,
1376+ labelShift = 0 ,
13761377 gridWidth = Plotly . Drawing . crispRound ( td , ax . gridwidth , 1 ) ,
13771378 zeroLineWidth = Plotly . Drawing . crispRound ( td , ax . zerolinewidth , gridWidth ) ,
13781379 tickWidth = Plotly . Drawing . crispRound ( td , ax . tickwidth , 1 ) ,
1379- sides , transfn , tickprefix , tickmid ,
1380+ sides , transfn , tickpathfn ,
13801381 i ;
13811382
1383+ if ( ax . _counterangle && ax . ticks === 'outside' ) {
1384+ var caRad = ax . _counterangle * Math . PI / 180 ;
1385+ labelStandoff = ax . ticklen * Math . cos ( caRad ) + ( ax . linewidth || 0 ) ;
1386+ labelShift = ax . ticklen * Math . sin ( caRad ) ;
1387+ }
1388+
13821389 // positioning arguments for x vs y axes
13831390 if ( axletter === 'x' ) {
13841391 sides = [ 'bottom' , 'top' ] ;
@@ -1387,16 +1394,26 @@ axes.doTicks = function(td, axid, skipTitle) {
13871394 } ;
13881395 // dumb templating with string concat
13891396 // would be better to use an actual template
1390- tickprefix = 'M0,' ;
1391- tickmid = 'v' ;
1397+ tickpathfn = function ( shift , len ) {
1398+ if ( ax . _counterangle ) {
1399+ var caRad = ax . _counterangle * Math . PI / 180 ;
1400+ return 'M0,' + shift + 'l' + ( Math . sin ( caRad ) * len ) + ',' + ( Math . cos ( caRad ) * len ) ;
1401+ }
1402+ else return 'M0,' + shift + 'v' + len ;
1403+ } ;
13921404 }
13931405 else if ( axletter === 'y' ) {
13941406 sides = [ 'left' , 'right' ] ;
13951407 transfn = function ( d ) {
13961408 return 'translate(0,' + ax . l2p ( d . x ) + ')' ;
13971409 } ;
1398- tickprefix = 'M' ;
1399- tickmid = ',0h' ;
1410+ tickpathfn = function ( shift , len ) {
1411+ if ( ax . _counterangle ) {
1412+ var caRad = ax . _counterangle * Math . PI / 180 ;
1413+ return 'M' + shift + ',0l' + ( Math . cos ( caRad ) * len ) + ',' + ( - Math . sin ( caRad ) * len ) ;
1414+ }
1415+ else return 'M' + shift + ',0h' + len ;
1416+ } ;
14001417 }
14011418 else {
14021419 console . log ( 'unrecognized doTicks axis' , axid ) ;
@@ -1444,10 +1461,10 @@ axes.doTicks = function(td, axid, skipTitle) {
14441461 return ;
14451462 }
14461463
1447- var labelx , labely , labelanchor , labelpos0 ;
1464+ var labelx , labely , labelanchor , labelpos0 , flipit ;
14481465 if ( axletter === 'x' ) {
1449- var flipit = axside === 'bottom' ? 1 : - 1 ;
1450- labelx = function ( d ) { return d . dx ; } ;
1466+ flipit = axside === 'bottom' ? 1 : - 1 ;
1467+ labelx = function ( d ) { return d . dx + labelShift * flipit ; } ;
14511468 labelpos0 = position + ( labelStandoff + pad ) * flipit ;
14521469 labely = function ( d ) {
14531470 return d . dy + labelpos0 + d . fontSize *
@@ -1461,11 +1478,11 @@ axes.doTicks = function(td, axid, skipTitle) {
14611478 } ;
14621479 }
14631480 else {
1464- labely = function ( d ) { return d . dy + d . fontSize / 2 ; } ;
1481+ flipit = axside === 'right' ? 1 : - 1 ;
1482+ labely = function ( d ) { return d . dy + d . fontSize / 2 - labelShift * flipit ; } ;
14651483 labelx = function ( d ) {
14661484 return d . dx + position + ( labelStandoff + pad +
1467- ( Math . abs ( ax . tickangle ) === 90 ? d . fontSize / 2 : 0 ) ) *
1468- ( axside === 'right' ? 1 : - 1 ) ;
1485+ ( Math . abs ( ax . tickangle ) === 90 ? d . fontSize / 2 : 0 ) ) * flipit ;
14691486 } ;
14701487 labelanchor = function ( angle ) {
14711488 if ( isNumeric ( angle ) && Math . abs ( angle ) === 90 ) {
@@ -1630,8 +1647,8 @@ axes.doTicks = function(td, axid, skipTitle) {
16301647 var gridcontainer = plotinfo . gridlayer ,
16311648 zlcontainer = plotinfo . zerolinelayer ,
16321649 gridvals = plotinfo [ 'hidegrid' + axletter ] ?[ ] :valsClipped ,
1633- gridpath = 'M0,0' + ( ( axletter === 'x' ) ? 'v' : 'h' ) +
1634- counteraxis . _length ,
1650+ gridpath = ax . _gridpath ||
1651+ 'M0,0' + ( ( axletter === 'x' ) ? 'v' : 'h' ) + counteraxis . _length ,
16351652 grid = gridcontainer . selectAll ( 'path.' + gcls )
16361653 . data ( ax . showgrid === false ? [ ] : gridvals , datafn ) ;
16371654 grid . enter ( ) . append ( 'path' ) . classed ( gcls , 1 )
@@ -1649,31 +1666,38 @@ axes.doTicks = function(td, axid, skipTitle) {
16491666 grid . exit ( ) . remove ( ) ;
16501667
16511668 // zero line
1652- var hasBarsOrFill = false ;
1653- for ( var i = 0 ; i < td . _fullData . length ; i ++ ) {
1654- if ( traceHasBarsOrFill ( td . _fullData [ i ] , subplot ) ) {
1655- hasBarsOrFill = true ;
1656- break ;
1669+ if ( zlcontainer ) {
1670+ var hasBarsOrFill = false ;
1671+ for ( var i = 0 ; i < td . _fullData . length ; i ++ ) {
1672+ if ( traceHasBarsOrFill ( td . _fullData [ i ] , subplot ) ) {
1673+ hasBarsOrFill = true ;
1674+ break ;
1675+ }
16571676 }
1677+ var showZl = ( ax . range [ 0 ] * ax . range [ 1 ] <= 0 ) && ax . zeroline &&
1678+ ( ax . type === 'linear' || ax . type === '-' ) && gridvals . length &&
1679+ ( hasBarsOrFill || clipEnds ( { x : 0 } ) || ! ax . showline ) ;
1680+ var zl = zlcontainer . selectAll ( 'path.' + zcls )
1681+ . data ( showZl ? [ { x : 0 } ] : [ ] ) ;
1682+ zl . enter ( ) . append ( 'path' ) . classed ( zcls , 1 ) . classed ( 'zl' , 1 )
1683+ . classed ( 'crisp' , 1 )
1684+ . attr ( 'd' , gridpath ) ;
1685+ zl . attr ( 'transform' , transfn )
1686+ . call ( Plotly . Color . stroke , ax . zerolinecolor || Plotly . Color . defaultLine )
1687+ . style ( 'stroke-width' , zeroLineWidth + 'px' ) ;
1688+ zl . exit ( ) . remove ( ) ;
16581689 }
1659- var showZl = ( ax . range [ 0 ] * ax . range [ 1 ] <= 0 ) && ax . zeroline &&
1660- ( ax . type === 'linear' || ax . type === '-' ) && gridvals . length &&
1661- ( hasBarsOrFill || clipEnds ( { x : 0 } ) || ! ax . showline ) ;
1662-
1663- var zl = zlcontainer . selectAll ( 'path.' + zcls )
1664- . data ( showZl ? [ { x : 0 } ] : [ ] ) ;
1665- zl . enter ( ) . append ( 'path' ) . classed ( zcls , 1 ) . classed ( 'zl' , 1 )
1666- . classed ( 'crisp' , 1 )
1667- . attr ( 'd' , gridpath ) ;
1668- zl . attr ( 'transform' , transfn )
1669- . call ( Plotly . Color . stroke , ax . zerolinecolor || Plotly . Color . defaultLine )
1670- . style ( 'stroke-width' , zeroLineWidth + 'px' ) ;
1671- zl . exit ( ) . remove ( ) ;
16721690 }
16731691
16741692 if ( independent ) {
1675- drawTicks ( ax . _axislayer , tickprefix + ( ax . _pos + pad * ticksign [ 2 ] ) +
1676- tickmid + ( ticksign [ 2 ] * ax . ticklen ) ) ;
1693+ drawTicks ( ax . _axislayer , tickpathfn ( ax . _pos + pad * ticksign [ 2 ] , ticksign [ 2 ] * ax . ticklen ) ) ;
1694+ if ( ax . _counteraxis ) {
1695+ var fictionalPlotinfo = {
1696+ gridlayer : ax . _gridlayer ,
1697+ zerolinelayer : ax . _zerolinelayer
1698+ } ;
1699+ drawGrid ( fictionalPlotinfo , ax . _counteraxis ) ;
1700+ }
16771701 return drawLabels ( ax . _axislayer , ax . _pos ) ;
16781702 }
16791703 else {
@@ -1713,8 +1737,7 @@ axes.doTicks = function(td, axid, skipTitle) {
17131737 var pos = linepositions [ sidei ] ,
17141738 tsign = ticksign [ sidei ] ;
17151739 if ( showside && isNumeric ( pos ) ) {
1716- tickpath += tickprefix + ( pos + pad * tsign ) +
1717- tickmid + ( tsign * ax . ticklen ) ;
1740+ tickpath += tickpathfn ( pos + pad * tsign , tsign * ax . ticklen ) ;
17181741 }
17191742 } ) ;
17201743
0 commit comments