Chart.js/src/charts/chart.polarArea.js

347 lines
13 KiB
JavaScript
Raw Normal View History

2015-05-27 06:02:41 +02:00
(function() {
"use strict";
var root = this,
Chart = root.Chart,
//Cache a local reference to Chart.helpers
helpers = Chart.helpers;
var defaultConfig = {
scale: {
type: "radialLinear",
lineArc: true, // so that lines are circular
},
//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.scaleService.getScaleConstructor(this.options.scale.type);
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,
data: this.data
});
helpers.bindEvents(this, this.options.events, this.events);
//Set up tooltip events on the chart
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);
}, 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);
// 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();
// Update the chart with the latest data.
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
});
},
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];
helpers.extend(slice, {
_index: index,
_model: {
x: this.chart.width / 2,
y: this.chart.height / 2,
innerRadius: 0,
outerRadius: 0,
startAngle: Math.PI * -0.5,
endAngle: Math.PI * -0.5,
backgroundColor: slice.custom && slice.custom.backgroundColor ? slice.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[0].backgroundColor, index, this.options.elements.arc.backgroundColor),
hoverBackgroundColor: slice.custom && slice.custom.hoverBackgroundColor ? slice.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[0].hoverBackgroundColor, index, this.options.elements.arc.hoverBackgroundColor),
borderWidth: slice.custom && slice.custom.borderWidth ? slice.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.data.datasets[0].borderWidth, index, this.options.elements.arc.borderWidth),
borderColor: slice.custom && slice.custom.borderColor ? slice.custom.borderColor : helpers.getValueAtIndexOrDefault(this.data.datasets[0].borderColor, index, this.options.elements.arc.borderColor),
label: helpers.getValueAtIndexOrDefault(this.data.datasets[0].labels, index, this.data.datasets[0].labels[index])
},
});
slice.pivot();
}, this);
},
update: function(animationDuration) {
this.updateScaleRange();
this.scale.calculateRange();
this.scale.generateTicks();
this.scale.buildYLabels();
Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
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 = (-0.5 * Math.PI) + (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: this.scale.getDistanceFromCenterForValue(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.arc.backgroundColor),
hoverBackgroundColor: slice.custom && slice.custom.hoverBackgroundColor ? slice.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[0].hoverBackgroundColor, index, this.options.elements.arc.hoverBackgroundColor),
borderWidth: slice.custom && slice.custom.borderWidth ? slice.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.data.datasets[0].borderWidth, index, this.options.elements.arc.borderWidth),
borderColor: slice.custom && slice.custom.borderColor ? slice.custom.borderColor : helpers.getValueAtIndexOrDefault(this.data.datasets[0].borderColor, index, this.options.elements.arc.borderColor),
label: helpers.getValueAtIndexOrDefault(this.data.datasets[0].labels, index, this.data.datasets[0].labels[index])
},
});
slice.pivot();
console.log(slice);
}, this);
this.render(animationDuration);
},
draw: function(ease) {
var easingDecimal = ease || 1;
this.clear();
helpers.each(this.data.datasets[0].metaData, function(slice, index) {
slice.transition(easingDecimal).draw();
}, this);
this.scale.draw();
this.tooltip.transition(easingDecimal).draw();
},
events: function(e) {
// If exiting chart
if (e.type == 'mouseout') {
return this;
}
this.lastActive = this.lastActive || [];
// Find Active Elements
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);
// On Hover hook
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);
}
}
var dataset;
var index;
// Remove styling for last active (even if it may still be active)
if (this.lastActive.length) {
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.arc.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.arc.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.arc.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.arc.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.arc.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.arc.borderWidth);
}
break;
case 'dataset':
break;
default:
// Don't change anything
}
}
// Built in hover styling
if (this.active.length && this.options.hover.mode) {
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 + 1);
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.1).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.1).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);
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 + 1);
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.1).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.1).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);
}
break;
case 'dataset':
break;
default:
// Don't change anything
}
}
// Built in Tooltips
if (this.options.tooltips.enabled) {
// The usual updates
this.tooltip.initialize();
// Active
if (this.active.length) {
this.tooltip._model.opacity = 1;
helpers.extend(this.tooltip, {
_active: this.active,
});
this.tooltip.update();
} else {
// Inactive
this.tooltip._model.opacity = 0;
}
}
// 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);
this.eachElement(function(slice, index) {
if (slice.inRange(location.x, location.y)) {
elements.push(slice);
}
}, this);
return elements;
},
/*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;
},*/
});
2014-06-29 19:36:25 +02:00
}).call(this);