2015-05-16 04:54:01 +02:00
( function ( ) {
2015-06-13 16:15:21 +02:00
"use strict" ;
var root = this ,
Chart = root . Chart ,
//Cache a local reference to Chart.helpers
helpers = Chart . helpers ;
2015-06-16 03:14:11 +02:00
Chart . defaults . doughnut = {
2015-06-13 16:15:21 +02:00
animation : {
//Boolean - Whether we animate the rotation of the Doughnut
animateRotate : true ,
//Boolean - Whether we animate scaling the Doughnut from the centre
animateScale : false ,
} ,
hover : {
mode : 'single'
} ,
//The percentage of the chart that we cut out of the middle.
cutoutPercentage : 50 ,
2015-10-31 01:48:31 +01:00
// Need to override these to give a nice default
tooltips : {
callbacks : {
2015-10-31 23:09:11 +01:00
title : function ( ) { return '' ; } ,
2015-10-31 01:48:31 +01:00
label : function ( tooltipItem , data ) {
return data . labels [ tooltipItem . index ] + ': ' + data . datasets [ tooltipItem . datasetIndex ] . data [ tooltipItem . index ] ;
}
}
}
2015-06-13 16:15:21 +02:00
} ;
2015-06-16 06:47:20 +02:00
Chart . defaults . pie = helpers . clone ( Chart . defaults . doughnut ) ;
helpers . extend ( Chart . defaults . pie , {
cutoutPercentage : 0
} ) ;
2015-06-16 03:14:11 +02:00
2015-06-16 06:47:20 +02:00
Chart . controllers . doughnut = Chart . controllers . pie = function ( chart , datasetIndex ) {
2015-06-16 03:14:11 +02:00
this . initialize . call ( this , chart , datasetIndex ) ;
} ;
helpers . extend ( Chart . controllers . doughnut . prototype , {
initialize : function ( chart , datasetIndex ) {
this . chart = chart ;
this . index = datasetIndex ;
this . linkScales ( ) ;
this . addElements ( ) ;
} ,
2015-06-17 04:04:52 +02:00
updateIndex : function ( datasetIndex ) {
this . index = datasetIndex ;
} ,
2015-06-16 03:14:11 +02:00
linkScales : function ( ) {
// no scales for doughnut
} ,
getDataset : function ( ) {
return this . chart . data . datasets [ this . index ] ;
} ,
addElements : function ( ) {
this . getDataset ( ) . metaData = this . getDataset ( ) . metaData || [ ] ;
helpers . each ( this . getDataset ( ) . data , function ( value , index ) {
this . getDataset ( ) . metaData [ index ] = this . getDataset ( ) . metaData [ index ] || new Chart . elements . Arc ( {
_chart : this . chart . chart ,
_datasetIndex : this . index ,
_index : index ,
} ) ;
} , this ) ;
} ,
2015-06-20 01:51:28 +02:00
addElementAndReset : function ( index , colorForNewElement ) {
this . getDataset ( ) . metaData = this . getDataset ( ) . metaData || [ ] ;
var arc = new Chart . elements . Arc ( {
_chart : this . chart . chart ,
_datasetIndex : this . index ,
_index : index ,
} ) ;
2015-08-30 20:56:48 +02:00
if ( colorForNewElement && helpers . isArray ( this . getDataset ( ) . backgroundColor ) ) {
this . getDataset ( ) . backgroundColor . splice ( index , 0 , colorForNewElement ) ;
}
2015-06-16 03:14:11 +02:00
2015-06-20 01:51:28 +02:00
// Reset the point
this . updateElement ( arc , index , true ) ;
// Add to the points array
this . getDataset ( ) . metaData . splice ( index , 0 , arc ) ;
} ,
removeElement : function ( index ) {
this . getDataset ( ) . metaData . splice ( index , 1 ) ;
} ,
2015-06-16 03:14:11 +02:00
reset : function ( ) {
this . update ( true ) ;
} ,
2015-09-22 02:59:53 +02:00
buildOrUpdateElements : function buildOrUpdateElements ( ) {
2015-08-30 20:56:48 +02:00
// Make sure we have metaData for each data point
var numData = this . getDataset ( ) . data . length ;
var numArcs = this . getDataset ( ) . metaData . length ;
// Make sure that we handle number of datapoints changing
if ( numData < numArcs ) {
// Remove excess bars for data points that have been removed
2015-10-21 02:33:51 +02:00
this . getDataset ( ) . metaData . splice ( numData , numArcs - numData ) ;
2015-08-30 20:56:48 +02:00
} else if ( numData > numArcs ) {
// Add new elements
for ( var index = numArcs ; index < numData ; ++ index ) {
this . addElementAndReset ( index ) ;
}
}
2015-09-22 02:59:53 +02:00
} ,
2015-10-08 01:54:11 +02:00
getVisibleDatasetCount : function getVisibleDatasetCount ( ) {
return helpers . where ( this . chart . data . datasets , function ( ds ) { return helpers . isDatasetVisible ( ds ) ; } ) . length ;
} ,
// Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly
getRingIndex : function getRingIndex ( datasetIndex ) {
var ringIndex = 0 ;
for ( var j = 0 ; j < datasetIndex ; ++ j ) {
if ( helpers . isDatasetVisible ( this . chart . data . datasets [ j ] ) ) {
++ ringIndex ;
}
}
return ringIndex ;
} ,
2015-09-22 02:59:53 +02:00
update : function update ( reset ) {
this . chart . outerRadius = Math . max ( ( helpers . min ( [ this . chart . chart . width , this . chart . chart . height ] ) / 2 ) - this . chart . options . elements . arc . borderWidth / 2 , 0 ) ;
this . chart . innerRadius = Math . max ( this . chart . options . cutoutPercentage ? ( this . chart . outerRadius / 100 ) * ( this . chart . options . cutoutPercentage ) : 1 , 0 ) ;
2015-10-08 01:54:11 +02:00
this . chart . radiusLength = ( this . chart . outerRadius - this . chart . innerRadius ) / this . getVisibleDatasetCount ( ) ;
2015-09-22 02:59:53 +02:00
this . getDataset ( ) . total = 0 ;
helpers . each ( this . getDataset ( ) . data , function ( value ) {
this . getDataset ( ) . total += Math . abs ( value ) ;
} , this ) ;
2015-10-08 01:54:11 +02:00
this . outerRadius = this . chart . outerRadius - ( this . chart . radiusLength * this . getRingIndex ( this . index ) ) ;
2015-09-22 02:59:53 +02:00
this . innerRadius = this . outerRadius - this . chart . radiusLength ;
2015-08-30 20:56:48 +02:00
2015-06-16 03:14:11 +02:00
helpers . each ( this . getDataset ( ) . metaData , function ( arc , index ) {
2015-06-20 01:51:28 +02:00
this . updateElement ( arc , index , reset ) ;
} , this ) ;
} ,
updateElement : function ( arc , index , reset ) {
var resetModel = {
x : this . chart . chart . width / 2 ,
y : this . chart . chart . height / 2 ,
startAngle : Math . PI * - 0.5 , // use - PI / 2 instead of 3PI / 2 to make animations better. It means that we never deal with overflow during the transition function
circumference : ( this . chart . options . animation . animateRotate ) ? 0 : this . calculateCircumference ( this . getDataset ( ) . data [ index ] ) ,
outerRadius : ( this . chart . options . animation . animateScale ) ? 0 : this . outerRadius ,
innerRadius : ( this . chart . options . animation . animateScale ) ? 0 : this . innerRadius ,
} ;
helpers . extend ( arc , {
// Utility
_chart : this . chart . chart ,
_datasetIndex : this . index ,
_index : index ,
// Desired view properties
_model : reset ? resetModel : {
2015-06-16 03:14:11 +02:00
x : this . chart . chart . width / 2 ,
y : this . chart . chart . height / 2 ,
2015-06-20 01:51:28 +02:00
circumference : this . calculateCircumference ( this . getDataset ( ) . data [ index ] ) ,
outerRadius : this . outerRadius ,
innerRadius : this . innerRadius ,
2015-06-16 03:14:11 +02:00
2015-06-20 01:51:28 +02:00
backgroundColor : arc . custom && arc . custom . backgroundColor ? arc . custom . backgroundColor : helpers . getValueAtIndexOrDefault ( this . getDataset ( ) . backgroundColor , index , this . chart . options . elements . arc . backgroundColor ) ,
hoverBackgroundColor : arc . custom && arc . custom . hoverBackgroundColor ? arc . custom . hoverBackgroundColor : helpers . getValueAtIndexOrDefault ( this . getDataset ( ) . hoverBackgroundColor , index , this . chart . options . elements . arc . hoverBackgroundColor ) ,
borderWidth : arc . custom && arc . custom . borderWidth ? arc . custom . borderWidth : helpers . getValueAtIndexOrDefault ( this . getDataset ( ) . borderWidth , index , this . chart . options . elements . arc . borderWidth ) ,
borderColor : arc . custom && arc . custom . borderColor ? arc . custom . borderColor : helpers . getValueAtIndexOrDefault ( this . getDataset ( ) . borderColor , index , this . chart . options . elements . arc . borderColor ) ,
2015-06-16 03:14:11 +02:00
2015-06-20 01:51:28 +02:00
label : helpers . getValueAtIndexOrDefault ( this . getDataset ( ) . label , index , this . chart . data . labels [ index ] )
} ,
} ) ;
2015-06-16 03:14:11 +02:00
2015-06-20 01:51:28 +02:00
if ( ! reset ) {
2015-06-16 03:14:11 +02:00
2015-06-20 01:51:28 +02:00
if ( index === 0 ) {
arc . _model . startAngle = Math . PI * - 0.5 ; // use - PI / 2 instead of 3PI / 2 to make animations better. It means that we never deal with overflow during the transition function
} else {
arc . _model . startAngle = this . getDataset ( ) . metaData [ index - 1 ] . _model . endAngle ;
}
arc . _model . endAngle = arc . _model . startAngle + arc . _model . circumference ;
2015-06-16 03:14:11 +02:00
2015-06-20 01:51:28 +02:00
//Check to see if it's the last arc, if not get the next and update its start angle
if ( index < this . getDataset ( ) . data . length - 1 ) {
this . getDataset ( ) . metaData [ index + 1 ] . _model . startAngle = arc . _model . endAngle ;
2015-06-16 03:14:11 +02:00
}
2015-06-20 01:51:28 +02:00
}
2015-06-16 03:14:11 +02:00
2015-06-20 01:51:28 +02:00
arc . pivot ( ) ;
2015-06-16 03:14:11 +02:00
} ,
draw : function ( ease ) {
var easingDecimal = ease || 1 ;
helpers . each ( this . getDataset ( ) . metaData , function ( arc , index ) {
arc . transition ( easingDecimal ) . draw ( ) ;
} , this ) ;
} ,
2015-06-16 06:43:24 +02:00
setHoverStyle : function ( arc ) {
var dataset = this . chart . data . datasets [ arc . _datasetIndex ] ;
var index = arc . _index ;
2015-06-16 03:14:11 +02:00
2015-06-16 06:43:24 +02:00
arc . _model . backgroundColor = arc . custom && arc . custom . hoverBackgroundColor ? arc . custom . hoverBackgroundColor : helpers . getValueAtIndexOrDefault ( dataset . hoverBackgroundColor , index , helpers . color ( arc . _model . backgroundColor ) . saturate ( 0.5 ) . darken ( 0.1 ) . rgbString ( ) ) ;
arc . _model . borderColor = arc . custom && arc . custom . hoverBorderColor ? arc . custom . hoverBorderColor : helpers . getValueAtIndexOrDefault ( dataset . hoverBorderColor , index , helpers . color ( arc . _model . borderColor ) . saturate ( 0.5 ) . darken ( 0.1 ) . rgbString ( ) ) ;
2015-08-30 20:56:48 +02:00
arc . _model . borderWidth = arc . custom && arc . custom . hoverBorderWidth ? arc . custom . hoverBorderWidth : helpers . getValueAtIndexOrDefault ( dataset . hoverBorderWidth , index , arc . _model . borderWidth ) ;
2015-06-16 03:14:11 +02:00
} ,
2015-06-16 06:43:24 +02:00
removeHoverStyle : function ( arc ) {
var dataset = this . chart . data . datasets [ arc . _datasetIndex ] ;
var index = arc . _index ;
arc . _model . backgroundColor = arc . custom && arc . custom . backgroundColor ? arc . custom . backgroundColor : helpers . getValueAtIndexOrDefault ( this . getDataset ( ) . backgroundColor , index , this . chart . options . elements . arc . backgroundColor ) ;
arc . _model . borderColor = arc . custom && arc . custom . borderColor ? arc . custom . borderColor : helpers . getValueAtIndexOrDefault ( this . getDataset ( ) . borderColor , index , this . chart . options . elements . arc . borderColor ) ;
arc . _model . borderWidth = arc . custom && arc . custom . borderWidth ? arc . custom . borderWidth : helpers . getValueAtIndexOrDefault ( this . getDataset ( ) . borderWidth , index , this . chart . options . elements . arc . borderWidth ) ;
2015-06-16 03:14:11 +02:00
} ,
calculateCircumference : function ( value ) {
if ( this . getDataset ( ) . total > 0 ) {
2015-06-16 19:46:50 +02:00
return ( Math . PI * 1.999999 ) * ( value / this . getDataset ( ) . total ) ;
2015-06-16 03:14:11 +02:00
} else {
return 0 ;
}
} ,
} ) ;
2014-10-21 03:49:41 +02:00
} ) . call ( this ) ;