Chart.js/src/Chart.PolarArea.js

404 lines
18 KiB
JavaScript
Raw Normal View History

2015-05-27 06:02:41 +02:00
(function() {
"use strict";
2014-06-29 19:36:25 +02:00
2015-05-27 06:02:41 +02:00
var root = this,
Chart = root.Chart,
//Cache a local reference to Chart.helpers
helpers = Chart.helpers;
2014-06-29 19:36:25 +02:00
2015-05-27 06:02:41 +02:00
var defaultConfig = {
2014-06-29 19:36:25 +02:00
2015-05-27 06:02:41 +02:00
scale: {
scaleType: "radialLinear",
display: true,
//Boolean - Whether to animate scaling the chart from the centre
animate: false,
lineArc: true,
// grid line settings
gridLines: {
show: true,
color: "rgba(0, 0, 0, 0.05)",
lineWidth: 1,
},
// scale numbers
beginAtZero: true,
// label settings
labels: {
show: true,
template: "<%=value%>",
fontSize: 12,
fontStyle: "normal",
fontColor: "#666",
fontFamily: "Helvetica Neue",
2015-05-27 06:02:41 +02:00
//Boolean - Show a backdrop to the scale label
showLabelBackdrop: true,
2015-05-27 06:02:41 +02:00
//String - The colour of the label backdrop
backdropColor: "rgba(255,255,255,0.75)",
2015-05-27 06:02:41 +02:00
//Number - The backdrop padding above & below the label in pixels
backdropPaddingY: 2,
2015-05-27 06:02:41 +02:00
//Number - The backdrop padding to the side of the label in pixels
backdropPaddingX: 2,
}
2015-05-27 06:02:41 +02:00
},
//Boolean - Whether to animate the rotation of the chart
animateRotate: true,
};
Chart.Type.extend({
//Passing in a name registers this chart in the Chart namespace
name: "PolarArea",
//Providing a defaults will also register the deafults in the chart namespace
defaults: defaultConfig,
//Initialize is fired when the chart is initialized - Data is passed in as a parameter
//Config is automatically merged by the core of Chart.js, and is available at this.options
initialize: function() {
// Scale setup
var self = this;
var ScaleClass = Chart.scales.getScaleConstructor(this.options.scale.scaleType);
this.scale = new ScaleClass({
options: this.options.scale,
lineArc: true,
width: this.chart.width,
height: this.chart.height,
xCenter: this.chart.width / 2,
yCenter: this.chart.height / 2,
ctx: this.chart.ctx,
valuesCount: this.data.length,
calculateRange: function() {
this.min = null;
this.max = null;
2015-06-03 22:45:40 +02:00
helpers.each(self.data.datasets[0].data, function(value) {
if (this.min === null) {
2015-06-03 22:45:40 +02:00
this.min = value;
} else if (value < this.min) {
this.min = value;
}
2015-05-27 06:02:41 +02:00
if (this.max === null) {
2015-06-03 22:45:40 +02:00
this.max = value;
} else if (value > this.max) {
this.max = value;
}
}, this);
2015-05-27 06:02:41 +02:00
}
});
2015-06-03 22:45:40 +02:00
helpers.bindEvents(this, this.options.events, this.events);
2015-05-27 06:02:41 +02:00
//Set up tooltip events on the chart
2015-06-03 22:45:40 +02:00
helpers.bindEvents(this, this.options.events, this.events);
//Create a new bar for each piece of data
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
dataset.metaData = [];
helpers.each(dataset.data, function(dataPoint, index) {
dataset.metaData.push(new Chart.Arc({
_chart: this.chart,
_datasetIndex: datasetIndex,
_index: index,
_model: {}
}));
}, this);
2015-05-27 06:02:41 +02:00
}, this);
// Create tooltip instance exclusively for this chart with some defaults.
this.tooltip = new Chart.Tooltip({
_chart: this.chart,
_data: this.data,
_options: this.options,
}, this);
2015-06-04 01:24:29 +02:00
// Fit the scale before we animate
this.updateScaleRange();
this.scale.calculateRange();
Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
// so that we animate nicely
this.resetElements();
2015-06-03 22:45:40 +02:00
// Update the chart with the latest data.
2015-05-27 06:02:41 +02:00
this.update();
},
updateScaleRange: function() {
helpers.extend(this.scale, {
size: helpers.min([this.chart.width, this.chart.height]),
xCenter: this.chart.width / 2,
yCenter: this.chart.height / 2
});
},
2015-06-04 01:24:29 +02:00
resetElements: function() {
var circumference = 1 / this.data.datasets[0].data.length * 2;
// Map new data to data points
helpers.each(this.data.datasets[0].metaData, function(slice, index) {
var value = this.data.datasets[0].data[index];
var startAngle = Math.PI * 1.5 + (Math.PI * circumference) * index;
var endAngle = startAngle + (circumference * Math.PI);
helpers.extend(slice, {
_index: index,
_model: {
x: this.chart.width / 2,
y: this.chart.height / 2,
innerRadius: 0,
outerRadius: 0,
startAngle: Math.PI * 1.5,
endAngle: Math.PI * 1.5,
backgroundColor: slice.custom && slice.custom.backgroundColor ? slice.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[0].backgroundColor, index, this.options.elements.slice.backgroundColor),
hoverBackgroundColor: slice.custom && slice.custom.hoverBackgroundColor ? slice.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[0].hoverBackgroundColor, index, this.options.elements.slice.hoverBackgroundColor),
borderWidth: slice.custom && slice.custom.borderWidth ? slice.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.data.datasets[0].borderWidth, index, this.options.elements.slice.borderWidth),
borderColor: slice.custom && slice.custom.borderColor ? slice.custom.borderColor : helpers.getValueAtIndexOrDefault(this.data.datasets[0].borderColor, index, this.options.elements.slice.borderColor),
label: helpers.getValueAtIndexOrDefault(this.data.datasets[0].labels, index, this.data.datasets[0].labels[index])
},
});
slice.pivot();
}, this);
},
2015-05-27 06:02:41 +02:00
update: function() {
this.updateScaleRange();
this.scale.calculateRange();
this.scale.generateTicks();
this.scale.buildYLabels();
2015-06-03 22:45:40 +02:00
Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
2015-05-27 06:02:41 +02:00
2015-06-03 22:45:40 +02:00
var circumference = 1 / this.data.datasets[0].data.length * 2;
2015-05-27 06:02:41 +02:00
// Map new data to data points
2015-06-03 22:45:40 +02:00
helpers.each(this.data.datasets[0].metaData, function(slice, index) {
2015-05-27 06:02:41 +02:00
2015-06-03 22:45:40 +02:00
var value = this.data.datasets[0].data[index];
2015-05-27 06:02:41 +02:00
var startAngle = Math.PI * 1.5 + (Math.PI * circumference) * index;
var endAngle = startAngle + (circumference * Math.PI);
helpers.extend(slice, {
_index: index,
2015-06-03 22:45:40 +02:00
_model: {
x: this.chart.width / 2,
y: this.chart.height / 2,
innerRadius: 0,
outerRadius: this.scale.calculateCenterOffset(value),
startAngle: startAngle,
endAngle: endAngle,
backgroundColor: slice.custom && slice.custom.backgroundColor ? slice.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[0].backgroundColor, index, this.options.elements.slice.backgroundColor),
hoverBackgroundColor: slice.custom && slice.custom.hoverBackgroundColor ? slice.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[0].hoverBackgroundColor, index, this.options.elements.slice.hoverBackgroundColor),
borderWidth: slice.custom && slice.custom.borderWidth ? slice.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.data.datasets[0].borderWidth, index, this.options.elements.slice.borderWidth),
borderColor: slice.custom && slice.custom.borderColor ? slice.custom.borderColor : helpers.getValueAtIndexOrDefault(this.data.datasets[0].borderColor, index, this.options.elements.slice.borderColor),
label: helpers.getValueAtIndexOrDefault(this.data.datasets[0].labels, index, this.data.datasets[0].labels[index])
},
2015-05-27 06:02:41 +02:00
});
slice.pivot();
2015-06-03 22:45:40 +02:00
console.log(slice);
2015-05-27 06:02:41 +02:00
}, this);
this.render();
},
draw: function(ease) {
var easingDecimal = ease || 1;
this.clear();
2015-06-03 22:45:40 +02:00
helpers.each(this.data.datasets[0].metaData, function(slice, index) {
slice.transition(easingDecimal).draw();
2015-05-27 06:02:41 +02:00
}, this);
this.scale.draw();
2015-06-04 00:31:25 +02:00
this.tooltip.transition(easingDecimal).draw();
2015-06-03 22:45:40 +02:00
},
events: function(e) {
// If exiting chart
if (e.type == 'mouseout') {
return this;
}
this.lastActive = this.lastActive || [];
// Find Active Elements
2015-06-04 00:31:25 +02:00
this.active = function() {
switch (this.options.hover.mode) {
case 'single':
return this.getSliceAtEvent(e);
case 'label':
return this.getSlicesAtEvent(e);
case 'dataset':
return this.getDatasetAtEvent(e);
default:
return e;
}
}.call(this);
2015-06-03 22:45:40 +02:00
// On Hover hook
2015-06-04 00:31:25 +02:00
if (this.options.hover.onHover) {
this.options.hover.onHover.call(this, this.active);
}
if (e.type == 'mouseup' || e.type == 'click') {
if (this.options.onClick) {
this.options.onClick.call(this, e, this.active);
}
2015-06-03 22:45:40 +02:00
}
2015-06-04 00:31:25 +02:00
var dataset;
var index;
2015-06-03 22:45:40 +02:00
// Remove styling for last active (even if it may still be active)
if (this.lastActive.length) {
2015-06-04 00:31:25 +02:00
switch (this.options.hover.mode) {
case 'single':
dataset = this.data.datasets[this.lastActive[0]._datasetIndex];
index = this.lastActive[0]._index;
this.lastActive[0]._model.backgroundColor = this.lastActive[0].custom && this.lastActive[0].custom.backgroundColor ? this.lastActive[0].custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, this.options.elements.slice.backgroundColor);
this.lastActive[0]._model.borderColor = this.lastActive[0].custom && this.lastActive[0].custom.borderColor ? this.lastActive[0].custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, this.options.elements.slice.borderColor);
this.lastActive[0]._model.borderWidth = this.lastActive[0].custom && this.lastActive[0].custom.borderWidth ? this.lastActive[0].custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, this.options.elements.slice.borderWidth);
break;
case 'label':
for (var i = 0; i < this.lastActive.length; i++) {
dataset = this.data.datasets[this.lastActive[i]._datasetIndex];
index = this.lastActive[i]._index;
this.lastActive[i]._model.backgroundColor = this.lastActive[i].custom && this.lastActive[i].custom.backgroundColor ? this.lastActive[i].custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, this.options.elements.slice.backgroundColor);
this.lastActive[i]._model.borderColor = this.lastActive[i].custom && this.lastActive[i].custom.borderColor ? this.lastActive[i].custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, this.options.elements.slice.borderColor);
this.lastActive[i]._model.borderWidth = this.lastActive[i].custom && this.lastActive[i].custom.borderWidth ? this.lastActive[i].custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, this.options.elements.slice.borderWidth);
}
break;
case 'dataset':
break;
default:
// Don't change anything
}
2015-06-03 22:45:40 +02:00
}
// Built in hover styling
if (this.active.length && this.options.hover.mode) {
2015-06-04 00:31:25 +02:00
switch (this.options.hover.mode) {
case 'single':
dataset = this.data.datasets[this.active[0]._datasetIndex];
index = this.active[0]._index;
this.active[0]._model.radius = this.active[0].custom && this.active[0].custom.hoverRadius ? this.active[0].custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.active[0]._model.radius + 2);
this.active[0]._model.backgroundColor = this.active[0].custom && this.active[0].custom.hoverBackgroundColor ? this.active[0].custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(this.active[0]._model.backgroundColor).saturate(0.5).darken(0.35).rgbString());
this.active[0]._model.borderColor = this.active[0].custom && this.active[0].custom.hoverBorderColor ? this.active[0].custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(this.active[0]._model.borderColor).saturate(0.5).darken(0.35).rgbString());
this.active[0]._model.borderWidth = this.active[0].custom && this.active[0].custom.hoverBorderWidth ? this.active[0].custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.active[0]._model.borderWidth + 2);
break;
case 'label':
for (var i = 0; i < this.active.length; i++) {
dataset = this.data.datasets[this.active[i]._datasetIndex];
index = this.active[i]._index;
this.active[i]._model.radius = this.active[i].custom && this.active[i].custom.hoverRadius ? this.active[i].custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.active[i]._model.radius + 2);
this.active[i]._model.backgroundColor = this.active[i].custom && this.active[i].custom.hoverBackgroundColor ? this.active[i].custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(this.active[i]._model.backgroundColor).saturate(0.5).darken(0.35).rgbString());
this.active[i]._model.borderColor = this.active[i].custom && this.active[i].custom.hoverBorderColor ? this.active[i].custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(this.active[i]._model.borderColor).saturate(0.5).darken(0.35).rgbString());
this.active[i]._model.borderWidth = this.active[i].custom && this.active[i].custom.hoverBorderWidth ? this.active[i].custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.active[i]._model.borderWidth + 2);
}
break;
case 'dataset':
break;
default:
// Don't change anything
}
2015-06-03 22:45:40 +02:00
}
2015-06-04 00:31:25 +02:00
2015-06-03 22:45:40 +02:00
// Built in Tooltips
if (this.options.tooltips.enabled) {
// The usual updates
this.tooltip.initialize();
// Active
if (this.active.length) {
2015-06-04 00:31:25 +02:00
this.tooltip._model.opacity = 1;
2015-06-03 22:45:40 +02:00
helpers.extend(this.tooltip, {
_active: this.active,
});
this.tooltip.update();
} else {
// Inactive
2015-06-04 00:31:25 +02:00
this.tooltip._model.opacity = 0;
2015-06-03 22:45:40 +02:00
}
}
// Hover animations
this.tooltip.pivot();
if (!this.animating) {
var changed;
helpers.each(this.active, function(element, index) {
if (element !== this.lastActive[index]) {
changed = true;
}
}, this);
// If entering, leaving, or changing elements, animate the change via pivot
if ((!this.lastActive.length && this.active.length) ||
(this.lastActive.length && !this.active.length) ||
(this.lastActive.length && this.active.length && changed)) {
this.stop();
this.render(this.options.hover.animationDuration);
}
}
// Remember Last Active
this.lastActive = this.active;
return this;
},
getSliceAtEvent: function(e) {
var elements = [];
var location = helpers.getRelativePosition(e);
2015-06-04 00:31:25 +02:00
this.eachElement(function(slice, index) {
if (slice.inRange(location.x, location.y)) {
elements.push(slice);
}
2015-06-03 22:45:40 +02:00
}, this);
return elements;
},
2015-06-04 00:31:25 +02:00
/*getSlicesAtEvent: function(e) {
var elements = [];
var location = helpers.getRelativePosition(e);
this.eachElement(function(slice, index) {
if (slice.inGroupRange(location.x, location.y)) {
elements.push(slice);
}
}, this);
return elements;
},*/
2015-05-27 06:02:41 +02:00
});
2014-06-29 19:36:25 +02:00
}).call(this);