@@ -43,7 +43,7 @@ defaults.set('scale', {
4343 drawBorder : true ,
4444 drawOnChartArea : true ,
4545 drawTicks : true ,
46- tickLength : 10 ,
46+ tickLength : 8 ,
4747 tickWidth : ( _ctx , options ) => options . lineWidth ,
4848 tickColor : ( _ctx , options ) => options . color ,
4949 offset : false ,
@@ -75,7 +75,7 @@ defaults.set('scale', {
7575 mirror : false ,
7676 textStrokeWidth : 0 ,
7777 textStrokeColor : '' ,
78- padding : 0 ,
78+ padding : 3 ,
7979 display : true ,
8080 autoSkip : true ,
8181 autoSkipPadding : 3 ,
@@ -783,7 +783,7 @@ export default class Scale extends Element {
783783
784784 const labelSizes = me . _getLabelSizes ( ) ;
785785 const maxLabelWidth = labelSizes . widest . width ;
786- const maxLabelHeight = labelSizes . highest . height - labelSizes . highest . offset ;
786+ const maxLabelHeight = labelSizes . highest . height ;
787787
788788 // Estimate the width of each grid based on the canvas width, the maximum
789789 // label width and the number of tick intervals
@@ -822,104 +822,40 @@ export default class Scale extends Element {
822822 height : 0
823823 } ;
824824
825- const chart = me . chart ;
826- const opts = me . options ;
827- const tickOpts = opts . ticks ;
828- const titleOpts = opts . title ;
829- const gridLineOpts = opts . grid ;
825+ const { chart, options : { ticks : tickOpts , title : titleOpts , grid : gridOpts } } = me ;
830826 const display = me . _isVisible ( ) ;
831- const labelsBelowTicks = opts . position !== 'top' && me . axis === 'x' ;
832827 const isHorizontal = me . isHorizontal ( ) ;
833- const titleHeight = display && getTitleHeight ( titleOpts , chart . options . font ) ;
834-
835- // Width
836- if ( isHorizontal ) {
837- minSize . width = me . maxWidth ;
838- } else if ( display ) {
839- minSize . width = getTickMarkLength ( gridLineOpts ) + titleHeight ;
840- }
841828
842- // height
843- if ( ! isHorizontal ) {
844- minSize . height = me . maxHeight ; // fill all the height
845- } else if ( display ) {
846- minSize . height = getTickMarkLength ( gridLineOpts ) + titleHeight ;
847- }
829+ if ( display ) {
830+ const titleHeight = getTitleHeight ( titleOpts , chart . options . font ) ;
831+ if ( isHorizontal ) {
832+ minSize . width = me . maxWidth ;
833+ minSize . height = getTickMarkLength ( gridOpts ) + titleHeight ;
834+ } else {
835+ minSize . height = me . maxHeight ; // fill all the height
836+ minSize . width = getTickMarkLength ( gridOpts ) + titleHeight ;
837+ }
848838
849- // Don't bother fitting the ticks if we are not showing the labels
850- if ( tickOpts . display && display && me . ticks . length ) {
851- const labelSizes = me . _getLabelSizes ( ) ;
852- const firstLabelSize = labelSizes . first ;
853- const lastLabelSize = labelSizes . last ;
854- const widestLabelSize = labelSizes . widest ;
855- const highestLabelSize = labelSizes . highest ;
856- const lineSpace = highestLabelSize . offset * 0.8 ;
857- const tickPadding = tickOpts . padding ;
839+ // Don't bother fitting the ticks if we are not showing the labels
840+ if ( tickOpts . display && me . ticks . length ) {
841+ const { first, last, widest, highest} = me . _getLabelSizes ( ) ;
842+ const tickPadding = tickOpts . padding * 2 ;
843+ const angleRadians = toRadians ( me . labelRotation ) ;
844+ const cos = Math . cos ( angleRadians ) ;
845+ const sin = Math . sin ( angleRadians ) ;
858846
859- if ( isHorizontal ) {
847+ if ( isHorizontal ) {
860848 // A horizontal axis is more constrained by the height.
861- const isRotated = me . labelRotation !== 0 ;
862- const angleRadians = toRadians ( me . labelRotation ) ;
863- const cosRotation = Math . cos ( angleRadians ) ;
864- const sinRotation = Math . sin ( angleRadians ) ;
865-
866- const labelHeight = sinRotation * widestLabelSize . width
867- + cosRotation * ( highestLabelSize . height - ( isRotated ? highestLabelSize . offset : 0 ) )
868- + ( isRotated ? 0 : lineSpace ) ; // padding
869-
870- minSize . height = Math . min ( me . maxHeight , minSize . height + labelHeight + tickPadding ) ;
871-
872- const offsetLeft = me . getPixelForTick ( 0 ) - me . left ;
873- const offsetRight = me . right - me . getPixelForTick ( me . ticks . length - 1 ) ;
874- let paddingLeft , paddingRight ;
875-
876- // Ensure that our ticks are always inside the canvas. When rotated, ticks are right aligned
877- // which means that the right padding is dominated by the font height
878- if ( isRotated ) {
879- paddingLeft = labelsBelowTicks ?
880- cosRotation * firstLabelSize . width + sinRotation * firstLabelSize . offset :
881- sinRotation * ( firstLabelSize . height - firstLabelSize . offset ) ;
882- paddingRight = labelsBelowTicks ?
883- sinRotation * ( lastLabelSize . height - lastLabelSize . offset ) :
884- cosRotation * lastLabelSize . width + sinRotation * lastLabelSize . offset ;
885- } else if ( tickOpts . align === 'start' ) {
886- paddingLeft = 0 ;
887- paddingRight = lastLabelSize . width ;
888- } else if ( tickOpts . align === 'end' ) {
889- paddingLeft = firstLabelSize . width ;
890- paddingRight = 0 ;
849+ const labelHeight = sin * widest . width + cos * highest . height ;
850+ minSize . height = Math . min ( me . maxHeight , minSize . height + labelHeight + tickPadding ) ;
891851 } else {
892- paddingLeft = firstLabelSize . width / 2 ;
893- paddingRight = lastLabelSize . width / 2 ;
894- }
895-
896- // Adjust padding taking into account changes in offsets
897- // and add 3 px to move away from canvas edges
898- me . paddingLeft = Math . max ( ( paddingLeft - offsetLeft ) * me . width / ( me . width - offsetLeft ) , 0 ) + 3 ;
899- me . paddingRight = Math . max ( ( paddingRight - offsetRight ) * me . width / ( me . width - offsetRight ) , 0 ) + 3 ;
900- } else {
901852 // A vertical axis is more constrained by the width. Labels are the
902853 // dominant factor here, so get that length first and account for padding
903- const labelWidth = tickOpts . mirror ? 0 :
904- // use lineSpace for consistency with horizontal axis
905- // tickPadding is not implemented for horizontal
906- widestLabelSize . width + tickPadding + lineSpace ;
907-
908- minSize . width = Math . min ( me . maxWidth , minSize . width + labelWidth ) ;
909-
910- let paddingTop = lastLabelSize . height / 2 ;
911- let paddingBottom = firstLabelSize . height / 2 ;
912-
913- if ( tickOpts . align === 'start' ) {
914- paddingTop = 0 ;
915- paddingBottom = firstLabelSize . height ;
916- } else if ( tickOpts . align === 'end' ) {
917- paddingTop = lastLabelSize . height ;
918- paddingBottom = 0 ;
919- }
854+ const labelWidth = tickOpts . mirror ? 0 : cos * widest . width + sin * highest . height ;
920855
921- me . paddingTop = paddingTop ;
922- me . paddingBottom = paddingBottom ;
856+ minSize . width = Math . min ( me . maxWidth , minSize . width + labelWidth + tickPadding ) ;
857+ }
858+ me . _calculatePadding ( first , last , sin , cos ) ;
923859 }
924860 }
925861
@@ -934,6 +870,57 @@ export default class Scale extends Element {
934870 }
935871 }
936872
873+ _calculatePadding ( first , last , sin , cos ) {
874+ const me = this ;
875+ const { ticks : { align, padding} , position} = me . options ;
876+ const isRotated = me . labelRotation !== 0 ;
877+ const labelsBelowTicks = position !== 'top' && me . axis === 'x' ;
878+
879+ if ( me . isHorizontal ( ) ) {
880+ const offsetLeft = me . getPixelForTick ( 0 ) - me . left ;
881+ const offsetRight = me . right - me . getPixelForTick ( me . ticks . length - 1 ) ;
882+ let paddingLeft = 0 ;
883+ let paddingRight = 0 ;
884+
885+ // Ensure that our ticks are always inside the canvas. When rotated, ticks are right aligned
886+ // which means that the right padding is dominated by the font height
887+ if ( isRotated ) {
888+ if ( labelsBelowTicks ) {
889+ paddingLeft = cos * first . width ;
890+ paddingRight = sin * last . height ;
891+ } else {
892+ paddingLeft = sin * first . height ;
893+ paddingRight = cos * last . width ;
894+ }
895+ } else if ( align === 'start' ) {
896+ paddingRight = last . width ;
897+ } else if ( align === 'end' ) {
898+ paddingLeft = first . width ;
899+ } else {
900+ paddingLeft = first . width / 2 ;
901+ paddingRight = last . width / 2 ;
902+ }
903+
904+ // Adjust padding taking into account changes in offsets
905+ me . paddingLeft = Math . max ( ( paddingLeft - offsetLeft + padding ) * me . width / ( me . width - offsetLeft ) , 0 ) ;
906+ me . paddingRight = Math . max ( ( paddingRight - offsetRight + padding ) * me . width / ( me . width - offsetRight ) , 0 ) ;
907+ } else {
908+ let paddingTop = last . height / 2 ;
909+ let paddingBottom = first . height / 2 ;
910+
911+ if ( align === 'start' ) {
912+ paddingTop = 0 ;
913+ paddingBottom = first . height ;
914+ } else if ( align === 'end' ) {
915+ paddingTop = last . height ;
916+ paddingBottom = 0 ;
917+ }
918+
919+ me . paddingTop = paddingTop + padding ;
920+ me . paddingBottom = paddingBottom + padding ;
921+ }
922+ }
923+
937924 /**
938925 * Handle margins and padding interactions
939926 * @private
@@ -990,7 +977,13 @@ export default class Scale extends Element {
990977 let labelSizes = me . _labelSizes ;
991978
992979 if ( ! labelSizes ) {
993- me . _labelSizes = labelSizes = me . _computeLabelSizes ( ) ;
980+ const sampleSize = me . options . ticks . sampleSize ;
981+ let ticks = me . ticks ;
982+ if ( sampleSize < ticks . length ) {
983+ ticks = sample ( ticks , sampleSize ) ;
984+ }
985+
986+ me . _labelSizes = labelSizes = me . _computeLabelSizes ( ticks , ticks . length ) ;
994987 }
995988
996989 return labelSizes ;
@@ -1002,26 +995,17 @@ export default class Scale extends Element {
1002995 * @return {{ first: object, last: object, widest: object, highest: object } }
1003996 * @private
1004997 */
1005- _computeLabelSizes ( ) {
1006- const me = this ;
1007- const ctx = me . ctx ;
1008- const caches = me . _longestTextCache ;
1009- const sampleSize = me . options . ticks . sampleSize ;
998+ _computeLabelSizes ( ticks , length ) {
999+ const { ctx, _longestTextCache : caches } = this ;
10101000 const widths = [ ] ;
10111001 const heights = [ ] ;
1012- const offsets = [ ] ;
10131002 let widestLabelSize = 0 ;
10141003 let highestLabelSize = 0 ;
1015- let ticks = me . ticks ;
1016- if ( sampleSize < ticks . length ) {
1017- ticks = sample ( ticks , sampleSize ) ;
1018- }
1019- const length = ticks . length ;
10201004 let i , j , jlen , label , tickFont , fontString , cache , lineHeight , width , height , nestedLabel ;
10211005
10221006 for ( i = 0 ; i < length ; ++ i ) {
10231007 label = ticks [ i ] . label ;
1024- tickFont = me . _resolveTickFontOptions ( i ) ;
1008+ tickFont = this . _resolveTickFontOptions ( i ) ;
10251009 ctx . font = fontString = tickFont . string ;
10261010 cache = caches [ fontString ] = caches [ fontString ] || { data : { } , gc : [ ] } ;
10271011 lineHeight = tickFont . lineHeight ;
@@ -1043,7 +1027,6 @@ export default class Scale extends Element {
10431027 }
10441028 widths . push ( width ) ;
10451029 heights . push ( height ) ;
1046- offsets . push ( lineHeight / 2 ) ;
10471030 widestLabelSize = Math . max ( width , widestLabelSize ) ;
10481031 highestLabelSize = Math . max ( height , highestLabelSize ) ;
10491032 }
@@ -1052,13 +1035,7 @@ export default class Scale extends Element {
10521035 const widest = widths . indexOf ( widestLabelSize ) ;
10531036 const highest = heights . indexOf ( highestLabelSize ) ;
10541037
1055- function valueAt ( idx ) {
1056- return {
1057- width : widths [ idx ] || 0 ,
1058- height : heights [ idx ] || 0 ,
1059- offset : offsets [ idx ] || 0
1060- } ;
1061- }
1038+ const valueAt = ( idx ) => ( { width : widths [ idx ] || 0 , height : heights [ idx ] || 0 } ) ;
10621039
10631040 return {
10641041 first : valueAt ( 0 ) ,
@@ -1299,7 +1276,7 @@ export default class Scale extends Element {
12991276 tx2 = me . left + tl ;
13001277 } else if ( axis === 'x' ) {
13011278 if ( position === 'center' ) {
1302- borderValue = alignBorderValue ( ( chartArea . top + chartArea . bottom ) / 2 ) ;
1279+ borderValue = alignBorderValue ( ( chartArea . top + chartArea . bottom ) / 2 + 0.5 ) ;
13031280 } else if ( isObject ( position ) ) {
13041281 const positionAxisID = Object . keys ( position ) [ 0 ] ;
13051282 const value = position [ positionAxisID ] ;
@@ -1458,24 +1435,20 @@ export default class Scale extends Element {
14581435 x = pixel ;
14591436 if ( position === 'top' ) {
14601437 if ( crossAlign === 'near' || rotation !== 0 ) {
1461- textOffset = ( Math . sin ( rotation ) * halfCount + 0.5 ) * lineHeight ;
1462- textOffset -= ( rotation === 0 ? ( lineCount - 0.5 ) : Math . cos ( rotation ) * halfCount ) * lineHeight ;
1438+ textOffset = - lineCount * lineHeight + lineHeight / 2 ;
14631439 } else if ( crossAlign === 'center' ) {
1464- textOffset = - 1 * ( labelSizes . highest . height / 2 ) ;
1465- textOffset -= halfCount * lineHeight ;
1440+ textOffset = - labelSizes . highest . height / 2 - halfCount * lineHeight + lineHeight ;
14661441 } else {
1467- textOffset = ( - 1 * labelSizes . highest . height ) + ( 0.5 * lineHeight ) ;
1442+ textOffset = - labelSizes . highest . height + lineHeight / 2 ;
14681443 }
14691444 } else {
14701445 // eslint-disable-next-line no-lonely-if
14711446 if ( crossAlign === 'near' || rotation !== 0 ) {
1472- textOffset = Math . sin ( rotation ) * halfCount * lineHeight ;
1473- textOffset += ( rotation === 0 ? 0.5 : Math . cos ( rotation ) * halfCount ) * lineHeight ;
1447+ textOffset = lineHeight / 2 ;
14741448 } else if ( crossAlign === 'center' ) {
1475- textOffset = labelSizes . highest . height / 2 ;
1476- textOffset -= halfCount * lineHeight ;
1449+ textOffset = labelSizes . highest . height / 2 - halfCount * lineHeight ;
14771450 } else {
1478- textOffset = labelSizes . highest . height - ( ( lineCount - 0.5 ) * lineHeight ) ;
1451+ textOffset = labelSizes . highest . height - lineCount * lineHeight ;
14791452 }
14801453 }
14811454 } else {
@@ -1522,12 +1495,10 @@ export default class Scale extends Element {
15221495
15231496 _getYAxisLabelAlignment ( tl ) {
15241497 const me = this ;
1525- const { position, ticks} = me . options ;
1526- const { crossAlign, mirror, padding} = ticks ;
1498+ const { position, ticks : { crossAlign, mirror, padding} } = me . options ;
15271499 const labelSizes = me . _getLabelSizes ( ) ;
15281500 const tickAndPadding = tl + padding ;
15291501 const widest = labelSizes . widest . width ;
1530- const lineSpace = labelSizes . highest . offset * 0.8 ;
15311502
15321503 let textAlign ;
15331504 let x ;
@@ -1546,7 +1517,7 @@ export default class Scale extends Element {
15461517 x -= ( widest / 2 ) ;
15471518 } else {
15481519 textAlign = 'left' ;
1549- x = me . left + lineSpace ;
1520+ x = me . left ;
15501521 }
15511522 }
15521523 } else if ( position === 'right' ) {
@@ -1563,7 +1534,7 @@ export default class Scale extends Element {
15631534 x += widest / 2 ;
15641535 } else {
15651536 textAlign = 'right' ;
1566- x = me . right - lineSpace ;
1537+ x = me . right ;
15671538 }
15681539 }
15691540 } else {
0 commit comments