@@ -276,7 +276,9 @@ var Scale = Element.extend({
276276 me . _maxLabelLines = 0 ;
277277 me . longestLabelWidth = 0 ;
278278 me . longestTextCache = me . longestTextCache || { } ;
279- me . _itemsToDraw = null ;
279+ me . _ticksToDraw = null ;
280+ me . _gridLineItems = null ;
281+ me . _labelItems = null ;
280282
281283 // Dimensions
282284 me . beforeSetDimensions ( ) ;
@@ -844,71 +846,84 @@ var Scale = Element.extend({
844846 return false ;
845847 } ,
846848
849+ _getTicksToDraw : function ( ) {
850+ var me = this ;
851+ var optionTicks = me . options . ticks ;
852+ var ticks = me . _ticksToDraw ;
853+
854+ if ( ticks ) {
855+ return ticks ;
856+ }
857+
858+ ticks = me . getTicks ( ) ;
859+
860+ if ( optionTicks . display && optionTicks . autoSkip ) {
861+ ticks = me . _autoSkip ( ticks ) ;
862+ }
863+
864+ me . _ticksToDraw = ticks ;
865+ return ticks ;
866+ } ,
867+
847868 /**
848869 * @private
849870 */
850- _computeItemsToDraw : function ( chartArea ) {
871+ _computeGridLineItems : function ( chartArea ) {
851872 var me = this ;
852873 var chart = me . chart ;
853874 var options = me . options ;
854- var optionTicks = options . ticks ;
855875 var gridLines = options . gridLines ;
856876 var position = options . position ;
857877 var offsetGridLines = gridLines . offsetGridLines ;
858-
859- var isRotated = me . labelRotation !== 0 ;
860- var isMirrored = optionTicks . mirror ;
861878 var isHorizontal = me . isHorizontal ( ) ;
862-
863- var ticks = optionTicks . display && optionTicks . autoSkip ? me . _autoSkip ( me . getTicks ( ) ) : me . getTicks ( ) ;
879+ var ticks = me . _getTicksToDraw ( ) ;
864880 var ticksLength = ticks . length + ( offsetGridLines ? 1 : 0 ) ;
865- var tickFonts = parseTickFontOptions ( optionTicks ) ;
866- var tickPadding = optionTicks . padding ;
867- var labelOffset = optionTicks . labelOffset ;
868-
869881 var tl = getTickMarkLength ( gridLines ) ;
870-
871- var labelRotationRadians = helpers . toRadians ( me . labelRotation ) ;
872-
873- var gridLineItems = [ ] ;
874- var labelItems = [ ] ;
875-
882+ var items = [ ] ;
876883 var axisWidth = gridLines . drawBorder ? valueAtIndexOrDefault ( gridLines . lineWidth , 0 , 0 ) : 0 ;
884+ var axisHalfWidth = axisWidth / 2 ;
877885 var alignPixel = helpers . _alignPixel ;
878- var borderValue , tickStart , tickEnd , i , tick ;
886+ var alignBorderValue = function ( pixel ) {
887+ return alignPixel ( chart , pixel , axisWidth ) ;
888+ } ;
889+ var borderValue , i , tick , label , lineValue , alignedLineValue ;
890+ var tx1 , ty1 , tx2 , ty2 , x1 , y1 , x2 , y2 , lineWidth , lineColor , borderDash , borderDashOffset ;
879891
880892 if ( position === 'top' ) {
881- borderValue = alignPixel ( chart , me . bottom , axisWidth ) ;
882- tickStart = me . bottom - tl ;
883- tickEnd = borderValue - axisWidth / 2 ;
893+ borderValue = alignBorderValue ( me . bottom ) ;
894+ ty1 = me . bottom - tl ;
895+ ty2 = borderValue - axisHalfWidth ;
896+ y1 = alignBorderValue ( chartArea . top ) + axisHalfWidth ;
897+ y2 = chartArea . bottom ;
884898 } else if ( position === 'bottom' ) {
885- borderValue = alignPixel ( chart , me . top , axisWidth ) ;
886- tickStart = borderValue + axisWidth / 2 ;
887- tickEnd = me . top + tl ;
899+ borderValue = alignBorderValue ( me . top ) ;
900+ y1 = chartArea . top ;
901+ y2 = alignBorderValue ( chartArea . bottom ) - axisHalfWidth ;
902+ ty1 = borderValue + axisHalfWidth ;
903+ ty2 = me . top + tl ;
888904 } else if ( position === 'left' ) {
889- borderValue = alignPixel ( chart , me . right , axisWidth ) ;
890- tickStart = me . right - tl ;
891- tickEnd = borderValue - axisWidth / 2 ;
905+ borderValue = alignBorderValue ( me . right ) ;
906+ tx1 = me . right - tl ;
907+ tx2 = borderValue - axisHalfWidth ;
908+ x1 = alignBorderValue ( chartArea . left ) + axisHalfWidth ;
909+ x2 = chartArea . right ;
892910 } else {
893- borderValue = alignPixel ( chart , me . left , axisWidth ) ;
894- tickStart = borderValue + axisWidth / 2 ;
895- tickEnd = me . left + tl ;
911+ borderValue = alignBorderValue ( me . left ) ;
912+ x1 = chartArea . left ;
913+ x2 = alignBorderValue ( chartArea . right ) - axisHalfWidth ;
914+ tx1 = borderValue + axisHalfWidth ;
915+ tx2 = me . left + tl ;
896916 }
897917
898918 for ( i = 0 ; i < ticksLength ; ++ i ) {
899919 tick = ticks [ i ] || { } ;
900-
901- var label = tick . label ;
902- var extra = i >= ticks . length ;
920+ label = tick . label ;
903921
904922 // autoskipper skipped this tick (#4635)
905- if ( helpers . isNullOrUndef ( label ) && ! extra ) {
923+ if ( helpers . isNullOrUndef ( label ) && i < ticks . length ) {
906924 continue ;
907925 }
908926
909- var tickFont = tick . major ? tickFonts . major : tickFonts . minor ;
910- var lineHeight = tickFont . lineHeight ;
911- var lineWidth , lineColor , borderDash , borderDashOffset ;
912927 if ( i === me . zeroLineIndex && options . offset === offsetGridLines ) {
913928 // Draw the first index specially
914929 lineWidth = gridLines . zeroLineWidth ;
@@ -922,114 +937,133 @@ var Scale = Element.extend({
922937 borderDashOffset = gridLines . borderDashOffset || 0.0 ;
923938 }
924939
925- // Common properties
926- var tx1 , ty1 , tx2 , ty2 , x1 , y1 , x2 , y2 , labelX , labelY , textOffset , textAlign ;
927- var labelCount = helpers . isArray ( label ) ? label . length : 1 ;
928- var lineValue = getPixelForGridLine ( me , i , offsetGridLines ) ;
940+ lineValue = getPixelForGridLine ( me , i , offsetGridLines ) ;
941+
942+ // Skip if the pixel is out of the range
943+ if ( lineValue === undefined ) {
944+ continue ;
945+ }
946+
947+ alignedLineValue = alignPixel ( chart , lineValue , lineWidth ) ;
929948
930949 if ( isHorizontal ) {
931- var labelYOffset = tl + tickPadding ;
932-
933- tx1 = tx2 = x1 = x2 = alignPixel ( chart , lineValue , lineWidth ) ;
934- ty1 = tickStart ;
935- ty2 = tickEnd ;
936- labelX = me . getPixelForTick ( i ) + labelOffset ; // x values for optionTicks (need to consider offsetLabel option)
937-
938- if ( position === 'top' ) {
939- y1 = alignPixel ( chart , chartArea . top , axisWidth ) + axisWidth / 2 ;
940- y2 = chartArea . bottom ;
941- textOffset = ( ( ! isRotated ? 0.5 : 1 ) - labelCount ) * lineHeight ;
942- textAlign = ! isRotated ? 'center' : 'left' ;
943- labelY = me . bottom - labelYOffset ;
944- } else {
945- y1 = chartArea . top ;
946- y2 = alignPixel ( chart , chartArea . bottom , axisWidth ) - axisWidth / 2 ;
947- textOffset = ( ! isRotated ? 0.5 : 0 ) * lineHeight ;
948- textAlign = ! isRotated ? 'center' : 'right' ;
949- labelY = me . top + labelYOffset ;
950- }
950+ tx1 = tx2 = x1 = x2 = alignedLineValue ;
951951 } else {
952- var labelXOffset = ( isMirrored ? 0 : tl ) + tickPadding ;
953-
954- tx1 = tickStart ;
955- tx2 = tickEnd ;
956- ty1 = ty2 = y1 = y2 = alignPixel ( chart , lineValue , lineWidth ) ;
957- labelY = me . getPixelForTick ( i ) + labelOffset ;
958- textOffset = ( 1 - labelCount ) * lineHeight / 2 ;
959-
960- if ( position === 'left' ) {
961- x1 = alignPixel ( chart , chartArea . left , axisWidth ) + axisWidth / 2 ;
962- x2 = chartArea . right ;
963- textAlign = isMirrored ? 'left' : 'right' ;
964- labelX = me . right - labelXOffset ;
965- } else {
966- x1 = chartArea . left ;
967- x2 = alignPixel ( chart , chartArea . right , axisWidth ) - axisWidth / 2 ;
968- textAlign = isMirrored ? 'right' : 'left' ;
969- labelX = me . left + labelXOffset ;
970- }
952+ ty1 = ty2 = y1 = y2 = alignedLineValue ;
971953 }
972954
973- if ( lineValue !== undefined ) {
974- gridLineItems . push ( {
975- tx1 : tx1 ,
976- ty1 : ty1 ,
977- tx2 : tx2 ,
978- ty2 : ty2 ,
979- x1 : x1 ,
980- y1 : y1 ,
981- x2 : x2 ,
982- y2 : y2 ,
983- width : lineWidth ,
984- color : lineColor ,
985- borderDash : borderDash ,
986- borderDashOffset : borderDashOffset ,
987- } ) ;
955+ items . push ( {
956+ tx1 : tx1 ,
957+ ty1 : ty1 ,
958+ tx2 : tx2 ,
959+ ty2 : ty2 ,
960+ x1 : x1 ,
961+ y1 : y1 ,
962+ x2 : x2 ,
963+ y2 : y2 ,
964+ width : lineWidth ,
965+ color : lineColor ,
966+ borderDash : borderDash ,
967+ borderDashOffset : borderDashOffset ,
968+ } ) ;
969+ }
970+
971+ items . ticksLength = ticksLength ;
972+ items . borderValue = borderValue ;
973+
974+ return items ;
975+ } ,
976+
977+ /**
978+ * @private
979+ */
980+ _computeLabelItems : function ( ) {
981+ var me = this ;
982+ var options = me . options ;
983+ var optionTicks = options . ticks ;
984+ var position = options . position ;
985+ var isMirrored = optionTicks . mirror ;
986+ var isHorizontal = me . isHorizontal ( ) ;
987+ var ticks = me . _getTicksToDraw ( ) ;
988+ var fonts = parseTickFontOptions ( optionTicks ) ;
989+ var tickPadding = optionTicks . padding ;
990+ var tl = getTickMarkLength ( options . gridLines ) ;
991+ var rotation = - helpers . toRadians ( me . labelRotation ) ;
992+ var items = [ ] ;
993+ var i , ilen , tick , label , x , y , textAlign , pixel , font , lineHeight , lineCount , textOffset ;
994+
995+ if ( position === 'top' ) {
996+ y = me . bottom - tl - tickPadding ;
997+ textAlign = ! rotation ? 'center' : 'left' ;
998+ } else if ( position === 'bottom' ) {
999+ y = me . top + tl + tickPadding ;
1000+ textAlign = ! rotation ? 'center' : 'right' ;
1001+ } else if ( position === 'left' ) {
1002+ x = me . right - ( isMirrored ? 0 : tl ) - tickPadding ;
1003+ textAlign = isMirrored ? 'left' : 'right' ;
1004+ } else {
1005+ x = me . right + ( isMirrored ? 0 : tl ) + tickPadding ;
1006+ textAlign = isMirrored ? 'right' : 'left' ;
1007+ }
1008+
1009+ for ( i = 0 , ilen = ticks . length ; i < ilen ; ++ i ) {
1010+ tick = ticks [ i ] ;
1011+ label = tick . label ;
1012+
1013+ // autoskipper skipped this tick (#4635)
1014+ if ( helpers . isNullOrUndef ( label ) ) {
1015+ continue ;
9881016 }
9891017
990- if ( ! extra ) {
991- labelItems . push ( {
992- x : labelX ,
993- y : labelY ,
994- rotation : - labelRotationRadians ,
995- label : label ,
996- font : tick . major ? tickFonts . major : tickFonts . minor ,
997- textOffset : textOffset ,
998- textAlign : textAlign
999- } ) ;
1018+ pixel = me . getPixelForTick ( i ) + optionTicks . labelOffset ;
1019+ font = tick . major ? fonts . major : fonts . minor ;
1020+ lineHeight = font . lineHeight ;
1021+ lineCount = helpers . isArray ( label ) ? label . length : 1 ;
1022+
1023+ if ( isHorizontal ) {
1024+ x = pixel ;
1025+ textOffset = position === 'top'
1026+ ? ( ( ! rotation ? 0.5 : 1 ) - lineCount ) * lineHeight
1027+ : ( ! rotation ? 0.5 : 0 ) * lineHeight ;
1028+ } else {
1029+ y = pixel ;
1030+ textOffset = ( 1 - lineCount ) * lineHeight / 2 ;
10001031 }
1001- }
10021032
1003- gridLineItems . ticksLength = ticksLength ;
1004- gridLineItems . borderValue = borderValue ;
1033+ items . push ( {
1034+ x : x ,
1035+ y : y ,
1036+ rotation : rotation ,
1037+ label : label ,
1038+ font : font ,
1039+ textOffset : textOffset ,
1040+ textAlign : textAlign
1041+ } ) ;
1042+ }
10051043
1006- return {
1007- gridLines : gridLineItems ,
1008- labels : labelItems
1009- } ;
1044+ return items ;
10101045 } ,
10111046
10121047 /**
10131048 * @private
10141049 */
10151050 _drawGrid : function ( chartArea ) {
10161051 var me = this ;
1017- var ctx = me . ctx ;
1018- var chart = me . chart ;
10191052 var gridLines = me . options . gridLines ;
10201053
10211054 if ( ! gridLines . display ) {
10221055 return ;
10231056 }
10241057
1058+ var ctx = me . ctx ;
1059+ var chart = me . chart ;
10251060 var alignPixel = helpers . _alignPixel ;
10261061 var axisWidth = gridLines . drawBorder ? valueAtIndexOrDefault ( gridLines . lineWidth , 0 , 0 ) : 0 ;
1027- var items = me . _itemsToDraw || ( me . _itemsToDraw = me . _computeItemsToDraw ( chartArea ) ) ;
1028- var gridLineItems = items . gridLines ;
1062+ var items = me . _gridLineItems || ( me . _gridLineItems = me . _computeGridLineItems ( chartArea ) ) ;
10291063 var width , color , i , ilen , item ;
10301064
1031- for ( i = 0 , ilen = gridLineItems . length ; i < ilen ; ++ i ) {
1032- item = gridLineItems [ i ] ;
1065+ for ( i = 0 , ilen = items . length ; i < ilen ; ++ i ) {
1066+ item = items [ i ] ;
10331067 width = item . width ;
10341068 color = item . color ;
10351069
@@ -1062,8 +1096,8 @@ var Scale = Element.extend({
10621096 if ( axisWidth ) {
10631097 // Draw the line at the edge of the axis
10641098 var firstLineWidth = axisWidth ;
1065- var lastLineWidth = valueAtIndexOrDefault ( gridLines . lineWidth , gridLineItems . ticksLength - 1 , 1 ) ;
1066- var borderValue = gridLineItems . borderValue ;
1099+ var lastLineWidth = valueAtIndexOrDefault ( gridLines . lineWidth , items . ticksLength - 1 , 1 ) ;
1100+ var borderValue = items . borderValue ;
10671101 var x1 , x2 , y1 , y2 ;
10681102
10691103 if ( me . isHorizontal ( ) ) {
@@ -1088,21 +1122,20 @@ var Scale = Element.extend({
10881122 /**
10891123 * @private
10901124 */
1091- _drawLabels : function ( chartArea ) {
1125+ _drawLabels : function ( ) {
10921126 var me = this ;
1093- var ctx = me . ctx ;
10941127 var optionTicks = me . options . ticks ;
10951128
10961129 if ( ! optionTicks . display ) {
10971130 return ;
10981131 }
10991132
1100- var items = me . _itemsToDraw || ( me . _itemsToDraw = me . _computeItemsToDraw ( chartArea ) ) ;
1101- var labelItems = items . labels ;
1133+ var ctx = me . ctx ;
1134+ var items = me . _labelItems || ( me . _labelItems = me . _computeLabelItems ( ) ) ;
11021135 var i , j , ilen , jlen , item , tickFont , label , y ;
11031136
1104- for ( i = 0 , ilen = labelItems . length ; i < ilen ; ++ i ) {
1105- item = labelItems [ i ] ;
1137+ for ( i = 0 , ilen = items . length ; i < ilen ; ++ i ) {
1138+ item = items [ i ] ;
11061139 tickFont = item . font ;
11071140
11081141 // Make sure we draw text in the correct color and font
@@ -1183,8 +1216,8 @@ var Scale = Element.extend({
11831216 }
11841217
11851218 me . _drawGrid ( chartArea ) ;
1186- me . _drawTitle ( chartArea ) ;
1187- me . _drawLabels ( chartArea ) ;
1219+ me . _drawTitle ( ) ;
1220+ me . _drawLabels ( ) ;
11881221 } ,
11891222
11901223 /**
0 commit comments