return Math.round(Math.random() * 255)
};
- var doughnutData = [{
- value: randomScalingFactor(),
- color: "#F7464A",
- highlight: "#FF5A5E",
- label: "Red"
- }, {
- value: randomScalingFactor(),
- color: "#46BFBD",
- highlight: "#5AD3D1",
- label: "Green"
- }, {
- value: randomScalingFactor(),
- color: "#FDB45C",
- highlight: "#FFC870",
- label: "Yellow"
- }, {
- value: randomScalingFactor(),
- color: "#949FB1",
- highlight: "#A8B3C5",
- label: "Grey"
- }, {
- value: randomScalingFactor(),
- color: "#4D5360",
- highlight: "#616774",
- label: "Dark Grey"
- }
+ var doughnutData = {
+ data: [{
+ value: randomScalingFactor(),
+ backgroundColor: "#F7464A",
+ hoverBackgroundColor: "#FF5A5E",
+ label: "Red"
+ }, {
+ value: randomScalingFactor(),
+ backgroundColor: "#46BFBD",
+ hoverBackgroundColor: "#5AD3D1",
+ label: "Green"
+ }, {
+ value: randomScalingFactor(),
+ backgroundColor: "#FDB45C",
+ hoverBackgroundColor: "#FFC870",
+ label: "Yellow"
+ }, {
+ value: randomScalingFactor(),
+ backgroundColor: "#949FB1",
+ hoverBackgroundColor: "#A8B3C5",
+ label: "Grey"
+ }, {
+ value: randomScalingFactor(),
+ backgroundColor: "#4D5360",
+ hoverBackgroundColor: "#616774",
+ label: "Dark Grey"
+ }
- ];
+ ]
+ };
window.onload = function() {
var ctx = document.getElementById("chart-area").getContext("2d");
};
$('#randomizeData').click(function() {
- $.each(doughnutData, function(i, piece) {
- doughnutData[i].value = randomScalingFactor();
- doughnutData[i].color = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)';
+ $.each(doughnutData.data, function(i, datapoint) {
+ datapoint.value = randomScalingFactor();
+ datapoint.backgroundColor = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)';
});
window.myDoughnut.update();
});
segmentStrokeColor: "#fff",
//Number - The width of each segment stroke
- segmentStrokeWidth: 2,
+ borderWidth: 2,
//The percentage of the chart that we cut out of the middle.
- percentageInnerCutout: 50,
+ cutoutPercentage: 50,
- //Number - Amount of animation steps
- animationSteps: 100,
+ // The duration of animations triggered by hover events
+ hoverAnimationDuration: 400,
//String - Animation easing effect
- animationEasing: "easeOutBounce",
+ animationEasing: "easeOutQuart",
//Boolean - Whether we animate the rotation of the Doughnut
animateRotate: true,
if (this.options.showTooltips) {
helpers.bindEvents(this, this.options.tooltipEvents, this.onHover);
}
- this.calculateTotal(data);
// Create new slice for each piece of data
- helpers.each(this.data.datasets, function(dataset, datasetIndex) {
- dataset.metaData = [];
- helpers.each(dataset.data, function(slice, index) {
- var metaSlice = new this.Slice();
- if (typeof slice == 'number') {
- helpers.extend(metaSlice, {
- value: slice
- });
- } else {
- helpers.extend(metaSlice, slice);
- }
- if (!metaSlice.color) {
- slice.color = 'hsl(' + (360 * index / data.length) + ', 100%, 50%)';
- }
- metaSlice.save();
- dataset.metaData.push(metaSlice);
- }, this);
+ this.data.metaData = [];
+ helpers.each(this.data.data, function(slice, index) {
+ var metaSlice = new this.Slice();
+ if (typeof slice == 'number') {
+ helpers.extend(metaSlice, {
+ value: slice
+ });
+ } else {
+ helpers.extend(metaSlice, slice);
+ }
+ helpers.extend(metaSlice, {
+ startAngle: Math.PI * 1.5,
+ circumference: (this.options.animateRotate) ? 0 : this.calculateCircumference(metaSlice.value),
+ outerRadius: (this.options.animateScale) ? 0 : this.outerRadius,
+ innerRadius: (this.options.animateScale) ? 0 : (this.outerRadius / 100) * this.options.percentageInnerCutout,
+ });
+ if (!metaSlice.backgroundColor) {
+ slice.backgroundColor = 'hsl(' + (360 * index / data.length) + ', 100%, 50%)';
+ }
+ metaSlice.save();
+ this.data.metaData.push(metaSlice);
}, this);
// Create tooltip instance exclusively for this chart with some defaults.
this.update();
},
- onHover: function(evt) {
+ onHover: function(e) {
// If exiting chart
if (e.type == 'mouseout') {
this.lastActive = this.lastActive || [];
// Find Active Elements
- this.active = function() {
- switch (this.options.hoverMode) {
- case 'single':
- return this.getElementAtEvent(e);
- case 'label':
- return this.getElementsAtEvent(e);
- case 'dataset':
- return this.getDatasetAtEvent(e);
- default:
- return e;
- }
- }.call(this);
+ this.active = this.getSliceAtEvent(e);
// On Hover hook
if (this.options.onHover) {
// Remove styling for last active (even if it may still be active)
if (this.lastActive.length) {
- switch (this.options.hoverMode) {
- case 'single':
- this.lastActive[0].backgroundColor = this.data.datasets[0].backgroundColor;
- break;
- case 'label':
- for (var i = 0; i < this.lastActive.length; i++) {
- this.lastActive[i].backgroundColor = this.data.datasets[this.lastActive[i]._datasetIndex].backgroundColor;
- }
- break;
- case 'dataset':
- break;
- default:
- // Don't change anything
- }
+ this.lastActive[0].backgroundColor = this.data.data[this.lastActive[0]._index].backgroundColor;
}
// Built in hover styling
if (this.active.length && this.options.hoverMode) {
- switch (this.options.hoverMode) {
- case 'single':
- this.active[0].backgroundColor = this.data.datasets[this.active[0]._datasetIndex].hoverBackgroundColor || helpers.color(this.active[0].backgroundColor).saturate(0.5).darken(0.35).rgbString();
- break;
- case 'label':
- for (var i = 0; i < this.active.length; i++) {
- this.active[i].backgroundColor = this.data.datasets[this.active[i]._datasetIndex].hoverBackgroundColor || helpers.color(this.active[i].backgroundColor).saturate(0.5).darken(0.35).rgbString();
- }
- break;
- case 'dataset':
- break;
- default:
- // Don't change anything
- }
+ this.active[0].backgroundColor = this.data.data[this.active[0]._index].hoverBackgroundColor || helpers.color(this.active[0].backgroundColor).saturate(0.5).darken(0.35).rgbString();
}
-
// Built in Tooltips
if (this.options.showTooltips) {
return this;
},
- getSegmentsAtEvent: function(e) {
- var segmentsArray = [];
+ getSliceAtEvent: function(e) {
+ var elements = [];
var location = helpers.getRelativePosition(e);
- helpers.each(this.segments, function(segment) {
- if (segment.inRange(location.x, location.y)) segmentsArray.push(segment);
+ helpers.each(this.data.metaData, function(slice, index) {
+ if (slice.inRange(location.x, location.y)) elements.push(slice);
}, this);
- return segmentsArray;
+ return elements;
},
calculateCircumference: function(value) {
if (this.total > 0) {
return 0;
}
},
- calculateTotal: function(data) {
- this.total = 0;
- helpers.each(data, function(segment) {
- this.total += Math.abs(segment.value);
- }, this);
- },
update: function() {
- this.outerRadius = (helpers.min([this.chart.width, this.chart.height]) - this.options.segmentStrokeWidth / 2) / 2;
+ // Calc Total
+ this.total = 0;
+ helpers.each(this.data.data, function(slice) {
+ this.total += Math.abs(slice.value);
+ }, this);
+ this.outerRadius = (helpers.min([this.chart.width, this.chart.height]) - this.options.borderWidth / 2) / 2;
// Map new data to data points
- helpers.each(this.data, function(segment, i) {
- helpers.extend(this.segments[i], {
+ helpers.each(this.data.metaData, function(slice, index) {
+
+ var datapoint = this.data.data[index];
+
+ helpers.extend(slice, {
+ _index: index,
x: this.chart.width / 2,
y: this.chart.height / 2,
- value: segment.value,
- backgroundColor: segment.color,
- hoverBackgroundColor: segment.highlight || segment.color,
- borderWidth: this.options.segmentStrokeWidth,
+ value: datapoint.value,
+ label: datapoint.label,
+ circumference: this.calculateCircumference(datapoint.value),
+ outerRadius: this.outerRadius,
+ innerRadius: (this.outerRadius / 100) * this.options.cutoutPercentage,
+
+ backgroundColor: datapoint.backgroundColor,
+ hoverBackgroundColor: datapoint.hoverBackgroundColor || datapoint.backgroundColor,
+ borderWidth: this.options.borderWidth,
borderColor: this.options.segmentStrokeColor,
- label: segment.label,
- startAngle: Math.PI * 1.5,
- circumference: (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value),
- innerRadius: (this.options.animateScale) ? 0 : (this.outerRadius / 100) * this.options.percentageInnerCutout,
- outerRadius: (this.options.animateScale) ? 0 : this.outerRadius,
});
- }, this);
- this.calculateTotal(this.segments);
+ helpers.extend(slice, {
+ endAngle: slice.startAngle + slice.circumference,
+ });
- // Reset any highlight colours before updating.
- helpers.each(this.activeElements, function(activeElement) {
- activeElement.restore(['backgroundColor']);
- });
+ if (index === 0) {
+ slice.startAngle = Math.PI * 1.5;
+ }
- helpers.each(this.segments, function(segment) {
- segment.save();
- });
- this.render();
- },
+ //Check to see if it's the last slice, if not get the next and update its start angle
+ if (index < this.data.data.length - 1) {
+ this.data.metaData[index + 1].startAngle = slice.endAngle;
+ }
- removeData: function(atIndex) {
- var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length - 1;
- this.segments.splice(indexToDelete, 1);
- this.reflow();
- this.update();
- },
+ slice.pivot();
- reflow: function() {
- helpers.extend(this.Slice.prototype, {
- x: this.chart.width / 2,
- y: this.chart.height / 2
- });
- this.outerRadius = (helpers.min([this.chart.width, this.chart.height]) - this.options.segmentStrokeWidth / 2) / 2;
- helpers.each(this.segments, function(segment) {
- segment.update({
- outerRadius: this.outerRadius,
- innerRadius: (this.outerRadius / 100) * this.options.percentageInnerCutout
- });
}, this);
+
+ this.render();
},
draw: function(easeDecimal) {
- var animDecimal = (easeDecimal) ? easeDecimal : 1;
+ easeDecimal = easeDecimal || 1;
this.clear();
- helpers.each(this.segments, function(segment, index) {
- segment.transition({
- circumference: this.calculateCircumference(segment.value),
- outerRadius: this.outerRadius,
- innerRadius: (this.outerRadius / 100) * this.options.percentageInnerCutout
- }, animDecimal);
-
- segment.endAngle = segment.startAngle + segment.circumference;
- segment.draw();
- if (index === 0) {
- segment.startAngle = Math.PI * 1.5;
- }
- //Check to see if it's the last segment, if not get the next and update the start angle
- if (index < this.segments.length - 1) {
- this.segments[index + 1].startAngle = segment.endAngle;
- }
+ helpers.each(this.data.metaData, function(slice, index) {
+ slice.transition(easeDecimal).draw();
}, this);
+ this.tooltip.transition(easeDecimal).draw();
}
});
Chart.types.Doughnut.extend({
name: "Pie",
defaults: helpers.merge(defaultConfig, {
- percentageInnerCutout: 0
+ cutoutPercentage: 0
})
});