mirror of
https://github.com/chartjs/Chart.js.git
synced 2026-03-23 00:26:52 +01:00
Prettified, and half way through doughut
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Bar Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
@@ -12,8 +13,8 @@
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function(){
|
||||
return (Math.random() > 0.5 ? 1.0 : -1.0) * Math.round(Math.random()*100)
|
||||
var randomScalingFactor = function() {
|
||||
return (Math.random() > 0.5 ? 1.0 : -1.0) * Math.round(Math.random() * 100)
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255)
|
||||
@@ -53,4 +54,5 @@
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@@ -1,80 +1,79 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Doughnut Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
body{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
#canvas-holder{
|
||||
width:30%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="canvas-holder">
|
||||
<canvas id="chart-area" width="500" height="500"/>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
|
||||
<head>
|
||||
<title>Doughnut Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#canvas-holder {
|
||||
width: 30%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<script>
|
||||
<body>
|
||||
<div id="canvas-holder" style="width:100%">
|
||||
<canvas id="chart-area" width="500" height="500" />
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100)
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255)
|
||||
};
|
||||
|
||||
var randomScalingFactor = function(){ return Math.round(Math.random()*100)};
|
||||
var randomColorFactor = function(){ 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 = [
|
||||
{
|
||||
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"
|
||||
}
|
||||
];
|
||||
|
||||
];
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("chart-area").getContext("2d");
|
||||
window.myDoughnut = new Chart(ctx).Doughnut(doughnutData, {
|
||||
responsive: true
|
||||
});
|
||||
};
|
||||
|
||||
window.onload = function(){
|
||||
var ctx = document.getElementById("chart-area").getContext("2d");
|
||||
window.myDoughnut = new Chart(ctx).Doughnut(doughnutData, {responsive : true});
|
||||
};
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(doughnutData, function(i, piece) {
|
||||
doughnutData[i].value = randomScalingFactor();
|
||||
doughnutData[i].color = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)';
|
||||
});
|
||||
window.myDoughnut.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
$('#randomizeData').click(function(){
|
||||
$.each(doughnutData, function(i, piece){
|
||||
doughnutData[i].value = randomScalingFactor();
|
||||
doughnutData[i].color = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)';
|
||||
});
|
||||
window.myDoughnut.update();
|
||||
});
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,66 +1,64 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Line Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div style="width:100%">
|
||||
<div>
|
||||
<canvas id="canvas" height="450" width="600"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
|
||||
<head>
|
||||
<title>Line Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
</head>
|
||||
|
||||
<script>
|
||||
var randomScalingFactor = function(){ return Math.round(Math.random()*100);};
|
||||
var randomColor = function(opacity){
|
||||
return 'rgba(' + Math.round(Math.random()*255) + ',' + Math.round(Math.random()*255) + ',' + Math.round(Math.random()*255) + ','+ (opacity || '.3') +')';
|
||||
};
|
||||
<body>
|
||||
<div style="width:100%">
|
||||
<div>
|
||||
<canvas id="canvas" height="450" width="600"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var lineChartData = {
|
||||
labels : ["January","February","March","April","May","June","July"],
|
||||
datasets : [
|
||||
{
|
||||
label: "My First dataset",
|
||||
data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()]
|
||||
},
|
||||
{
|
||||
label: "My Second dataset",
|
||||
data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()]
|
||||
}
|
||||
]
|
||||
};
|
||||
var lineChartData = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}]
|
||||
};
|
||||
|
||||
$.each(lineChartData.datasets, function(i, dataset){
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.1);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
console.log(lineChartData);
|
||||
|
||||
window.onload = function(){
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = new Chart(ctx).Line(lineChartData, {
|
||||
responsive: true,
|
||||
hoverMode: 'label'
|
||||
});
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function(){
|
||||
lineChartData.datasets[0].data = [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()];
|
||||
|
||||
lineChartData.datasets[1].data = [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()];
|
||||
|
||||
window.myLine.update();
|
||||
$.each(lineChartData.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.1);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
console.log(lineChartData);
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = new Chart(ctx).Line(lineChartData, {
|
||||
responsive: true,
|
||||
hoverMode: 'label'
|
||||
});
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
lineChartData.datasets[0].data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
|
||||
|
||||
lineChartData.datasets[1].data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
620
src/Chart.Bar.js
620
src/Chart.Bar.js
@@ -1,369 +1,365 @@
|
||||
(function(){
|
||||
"use strict";
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
var root = this,
|
||||
Chart = root.Chart,
|
||||
helpers = Chart.helpers;
|
||||
var root = this,
|
||||
Chart = root.Chart,
|
||||
helpers = Chart.helpers;
|
||||
|
||||
|
||||
var defaultConfig = {
|
||||
//Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
|
||||
scaleBeginAtZero : true,
|
||||
var defaultConfig = {
|
||||
//Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
|
||||
scaleBeginAtZero: true,
|
||||
|
||||
//Boolean - Whether grid lines are shown across the chart
|
||||
scaleShowGridLines : true,
|
||||
//Boolean - Whether grid lines are shown across the chart
|
||||
scaleShowGridLines: true,
|
||||
|
||||
//String - Colour of the grid lines
|
||||
scaleGridLineColor : "rgba(0,0,0,.05)",
|
||||
//String - Colour of the grid lines
|
||||
scaleGridLineColor: "rgba(0,0,0,.05)",
|
||||
|
||||
//Number - Width of the grid lines
|
||||
scaleGridLineWidth : 1,
|
||||
//Number - Width of the grid lines
|
||||
scaleGridLineWidth: 1,
|
||||
|
||||
//Boolean - Whether to show horizontal lines (except X axis)
|
||||
scaleShowHorizontalLines: true,
|
||||
//Boolean - Whether to show horizontal lines (except X axis)
|
||||
scaleShowHorizontalLines: true,
|
||||
|
||||
//Boolean - Whether to show vertical lines (except Y axis)
|
||||
scaleShowVerticalLines: true,
|
||||
//Boolean - Whether to show vertical lines (except Y axis)
|
||||
scaleShowVerticalLines: true,
|
||||
|
||||
//Number - Pixel width of the bar border
|
||||
barBorderWidth : 2,
|
||||
//Number - Pixel width of the bar border
|
||||
barBorderWidth: 2,
|
||||
|
||||
//Number - Spacing between each of the X value sets
|
||||
barValueSpacing : 5,
|
||||
//Number - Spacing between each of the X value sets
|
||||
barValueSpacing: 5,
|
||||
|
||||
//Number - Spacing between data sets within X values
|
||||
barDatasetSpacing : 1,
|
||||
//Number - Spacing between data sets within X values
|
||||
barDatasetSpacing: 1,
|
||||
|
||||
//String - A legend template
|
||||
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].backgroundColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
|
||||
//String - A legend template
|
||||
legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].backgroundColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Chart.Type.extend({
|
||||
name: "Bar",
|
||||
defaults : defaultConfig,
|
||||
initialize: function(data){
|
||||
Chart.Type.extend({
|
||||
name: "Bar",
|
||||
defaults: defaultConfig,
|
||||
initialize: function(data) {
|
||||
|
||||
// Save data as a source for updating of values & methods
|
||||
this.data = data;
|
||||
// Save data as a source for updating of values & methods
|
||||
this.data = data;
|
||||
|
||||
var options = this.options;
|
||||
var options = this.options;
|
||||
|
||||
// Custom Scale Methods and Options
|
||||
this.ScaleClass = Chart.Scale.extend({
|
||||
offsetGridLines : true,
|
||||
calculateBarX : function(datasetCount, datasetIndex, elementIndex){
|
||||
//Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar
|
||||
var xWidth = this.calculateBaseWidth(),
|
||||
xAbsolute = this.calculateX(elementIndex) - (xWidth/2),
|
||||
barWidth = this.calculateBarWidth(datasetCount);
|
||||
// Custom Scale Methods and Options
|
||||
this.ScaleClass = Chart.Scale.extend({
|
||||
offsetGridLines: true,
|
||||
calculateBarX: function(datasetCount, datasetIndex, elementIndex) {
|
||||
//Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar
|
||||
var xWidth = this.calculateBaseWidth(),
|
||||
xAbsolute = this.calculateX(elementIndex) - (xWidth / 2),
|
||||
barWidth = this.calculateBarWidth(datasetCount);
|
||||
|
||||
return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth/2;
|
||||
},
|
||||
calculateBaseWidth : function(){
|
||||
return (this.calculateX(1) - this.calculateX(0)) - (2*options.barValueSpacing);
|
||||
},
|
||||
calculateBarWidth : function(datasetCount){
|
||||
//The padding between datasets is to the right of each bar, providing that there are more than 1 dataset
|
||||
var baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing);
|
||||
return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth / 2;
|
||||
},
|
||||
calculateBaseWidth: function() {
|
||||
return (this.calculateX(1) - this.calculateX(0)) - (2 * options.barValueSpacing);
|
||||
},
|
||||
calculateBarWidth: function(datasetCount) {
|
||||
//The padding between datasets is to the right of each bar, providing that there are more than 1 dataset
|
||||
var baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing);
|
||||
|
||||
return (baseWidth / datasetCount);
|
||||
}
|
||||
});
|
||||
return (baseWidth / datasetCount);
|
||||
}
|
||||
});
|
||||
|
||||
// Events
|
||||
helpers.bindEvents(this, this.options.tooltipEvents, this.onHover);
|
||||
|
||||
//Declare the extension of the default point, to cater for the options passed in to the constructor
|
||||
this.BarClass = Chart.Rectangle.extend({
|
||||
ctx : this.chart.ctx,
|
||||
});
|
||||
// Events
|
||||
helpers.bindEvents(this, this.options.tooltipEvents, this.onHover);
|
||||
|
||||
// Build Scale
|
||||
this.buildScale(this.data.labels);
|
||||
//Declare the extension of the default point, to cater for the options passed in to the constructor
|
||||
this.BarClass = Chart.Rectangle.extend({
|
||||
ctx: this.chart.ctx,
|
||||
});
|
||||
|
||||
//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 this.BarClass());
|
||||
},this);
|
||||
},this);
|
||||
// Build Scale
|
||||
this.buildScale(this.data.labels);
|
||||
|
||||
// Set defaults for bars
|
||||
this.eachElement(function(bar, index, datasetIndex){
|
||||
helpers.extend(bar, {
|
||||
width : this.scale.calculateBarWidth(this.data.datasets.length),
|
||||
x: this.scale.calculateBarX(this.data.datasets.length, datasetIndex, index),
|
||||
y: this.calculateBaseY(),
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
});
|
||||
// Copy to view model
|
||||
bar.save();
|
||||
}, this);
|
||||
//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 this.BarClass());
|
||||
}, 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);
|
||||
// Set defaults for bars
|
||||
this.eachElement(function(bar, index, datasetIndex) {
|
||||
helpers.extend(bar, {
|
||||
width: this.scale.calculateBarWidth(this.data.datasets.length),
|
||||
x: this.scale.calculateBarX(this.data.datasets.length, datasetIndex, index),
|
||||
y: this.calculateBaseY(),
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
});
|
||||
// Copy to view model
|
||||
bar.save();
|
||||
}, this);
|
||||
|
||||
// Update the chart with the latest data.
|
||||
this.update();
|
||||
},
|
||||
onHover: function(e){
|
||||
// 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);
|
||||
|
||||
// Update the chart with the latest data.
|
||||
this.update();
|
||||
},
|
||||
onHover: function(e) {
|
||||
|
||||
|
||||
// If exiting chart
|
||||
if(e.type == 'mouseout'){
|
||||
return this;
|
||||
}
|
||||
// If exiting chart
|
||||
if (e.type == 'mouseout') {
|
||||
return this;
|
||||
}
|
||||
|
||||
this.lastActive = this.lastActive || [];
|
||||
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);
|
||||
// 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);
|
||||
|
||||
// On Hover hook
|
||||
if(this.options.onHover){
|
||||
this.options.onHover.call(this, this.active);
|
||||
}
|
||||
// On Hover hook
|
||||
if (this.options.onHover) {
|
||||
this.options.onHover.call(this, this.active);
|
||||
}
|
||||
|
||||
// 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[this.lastActive[0]._datasetIndex].backgroundColor;
|
||||
this.lastActive[0].borderColor = this.data.datasets[this.lastActive[0]._datasetIndex].borderColor;
|
||||
break;
|
||||
case 'label':
|
||||
for (var i = 0; i < this.lastActive.length; i++) {
|
||||
this.lastActive[i].backgroundColor = this.data.datasets[this.lastActive[i]._datasetIndex].backgroundColor;
|
||||
this.lastActive[i].borderColor = this.data.datasets[this.lastActive[i]._datasetIndex].borderColor;
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
this.active[0].borderColor = this.data.datasets[this.active[0]._datasetIndex].hoverBorderColor || helpers.color(this.active[0].borderColor).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();
|
||||
this.active[i].borderColor = this.data.datasets[this.active[i]._datasetIndex].hoverBorderColor || helpers.color(this.active[i].borderColor).saturate(0.5).darken(0.35).rgbString();
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
// 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[this.lastActive[0]._datasetIndex].backgroundColor;
|
||||
this.lastActive[0].borderColor = this.data.datasets[this.lastActive[0]._datasetIndex].borderColor;
|
||||
break;
|
||||
case 'label':
|
||||
for (var i = 0; i < this.lastActive.length; i++) {
|
||||
this.lastActive[i].backgroundColor = this.data.datasets[this.lastActive[i]._datasetIndex].backgroundColor;
|
||||
this.lastActive[i].borderColor = this.data.datasets[this.lastActive[i]._datasetIndex].borderColor;
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
this.active[0].borderColor = this.data.datasets[this.active[0]._datasetIndex].hoverBorderColor || helpers.color(this.active[0].borderColor).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();
|
||||
this.active[i].borderColor = this.data.datasets[this.active[i]._datasetIndex].hoverBorderColor || helpers.color(this.active[i].borderColor).saturate(0.5).darken(0.35).rgbString();
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Built in Tooltips
|
||||
if(this.options.showTooltips){
|
||||
// Built in Tooltips
|
||||
if (this.options.showTooltips) {
|
||||
|
||||
// The usual updates
|
||||
this.tooltip.initialize();
|
||||
// The usual updates
|
||||
this.tooltip.initialize();
|
||||
|
||||
// Active
|
||||
if(this.active.length){
|
||||
helpers.extend(this.tooltip, {
|
||||
opacity: 1,
|
||||
_active: this.active,
|
||||
});
|
||||
// Active
|
||||
if (this.active.length) {
|
||||
helpers.extend(this.tooltip, {
|
||||
opacity: 1,
|
||||
_active: this.active,
|
||||
});
|
||||
|
||||
this.tooltip.update();
|
||||
}
|
||||
else{
|
||||
// Inactive
|
||||
helpers.extend(this.tooltip, {
|
||||
opacity: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
this.tooltip.update();
|
||||
} else {
|
||||
// Inactive
|
||||
helpers.extend(this.tooltip, {
|
||||
opacity: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.tooltip.pivot();
|
||||
this.tooltip.pivot();
|
||||
|
||||
// Hover animations
|
||||
if(!this.animating){
|
||||
var changed;
|
||||
|
||||
helpers.each(this.active, function(element, index){
|
||||
if (element !== this.lastActive[index]){
|
||||
changed = true;
|
||||
}
|
||||
}, this);
|
||||
// Hover animations
|
||||
if (!this.animating) {
|
||||
var changed;
|
||||
|
||||
// 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)){
|
||||
helpers.each(this.active, function(element, index) {
|
||||
if (element !== this.lastActive[index]) {
|
||||
changed = true;
|
||||
}
|
||||
}, this);
|
||||
|
||||
this.stop();
|
||||
this.render(this.options.hoverAnimationDuration);
|
||||
}
|
||||
}
|
||||
// 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)) {
|
||||
|
||||
// Remember Last Active
|
||||
this.lastActive = this.active;
|
||||
return this;
|
||||
},
|
||||
// Calculate the base point for the bar.
|
||||
calculateBaseY: function() {
|
||||
var base = this.scale.endPoint;
|
||||
|
||||
if (this.scale.beginAtZero || ((this.scale.min <= 0 && this.scale.max >= 0) || (this.scale.min >= 0 && this.scale.max <= 0)))
|
||||
{
|
||||
base = this.scale.calculateY(0);
|
||||
base += this.options.scaleGridLineWidth;
|
||||
}
|
||||
else if (this.scale.min < 0 && this.scale.max < 0)
|
||||
{
|
||||
// All values are negative. Use the top as the base
|
||||
base = this.scale.startPoint;
|
||||
}
|
||||
|
||||
return base;
|
||||
},
|
||||
update : function(){
|
||||
this.stop();
|
||||
this.render(this.options.hoverAnimationDuration);
|
||||
}
|
||||
}
|
||||
|
||||
this.scale.update();
|
||||
// Remember Last Active
|
||||
this.lastActive = this.active;
|
||||
return this;
|
||||
},
|
||||
// Calculate the base point for the bar.
|
||||
calculateBaseY: function() {
|
||||
var base = this.scale.endPoint;
|
||||
|
||||
this.eachElement(function(bar, index, dataset, datasetIndex){
|
||||
helpers.extend(bar, {
|
||||
width : this.scale.calculateBarWidth(this.data.datasets.length),
|
||||
x: this.scale.calculateBarX(this.data.datasets.length, datasetIndex, index),
|
||||
y: this.scale.calculateY(this.data.datasets[datasetIndex].data[index]),
|
||||
value : this.data.datasets[datasetIndex].data[index],
|
||||
label : this.data.labels[index],
|
||||
datasetLabel: this.data.datasets[datasetIndex].label,
|
||||
borderColor : this.data.datasets[datasetIndex].borderColor,
|
||||
borderWidth : this.data.datasets[datasetIndex].borderWidth,
|
||||
backgroundColor : this.data.datasets[datasetIndex].backgroundColor,
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
});
|
||||
bar.pivot();
|
||||
}, this);
|
||||
if (this.scale.beginAtZero || ((this.scale.min <= 0 && this.scale.max >= 0) || (this.scale.min >= 0 && this.scale.max <= 0))) {
|
||||
base = this.scale.calculateY(0);
|
||||
base += this.options.scaleGridLineWidth;
|
||||
} else if (this.scale.min < 0 && this.scale.max < 0) {
|
||||
// All values are negative. Use the top as the base
|
||||
base = this.scale.startPoint;
|
||||
}
|
||||
|
||||
this.render();
|
||||
},
|
||||
buildScale : function(labels){
|
||||
var self = this;
|
||||
return base;
|
||||
},
|
||||
update: function() {
|
||||
|
||||
var dataTotal = function(){
|
||||
var values = [];
|
||||
self.eachValue(function(value){
|
||||
values.push(value);
|
||||
});
|
||||
return values;
|
||||
};
|
||||
this.scale.update();
|
||||
|
||||
var scaleOptions = {
|
||||
templateString : this.options.scaleLabel,
|
||||
height : this.chart.height,
|
||||
width : this.chart.width,
|
||||
ctx : this.chart.ctx,
|
||||
textColor : this.options.scaleFontColor,
|
||||
fontSize : this.options.scaleFontSize,
|
||||
fontStyle : this.options.scaleFontStyle,
|
||||
fontFamily : this.options.scaleFontFamily,
|
||||
valuesCount : labels.length,
|
||||
beginAtZero : this.options.scaleBeginAtZero,
|
||||
integersOnly : this.options.scaleIntegersOnly,
|
||||
calculateYRange: function(currentHeight){
|
||||
var updatedRanges = helpers.calculateScaleRange(
|
||||
dataTotal(),
|
||||
currentHeight,
|
||||
this.fontSize,
|
||||
this.beginAtZero,
|
||||
this.integersOnly
|
||||
);
|
||||
helpers.extend(this, updatedRanges);
|
||||
},
|
||||
xLabels : labels,
|
||||
font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
|
||||
lineWidth : this.options.scaleLineWidth,
|
||||
lineColor : this.options.scaleLineColor,
|
||||
showHorizontalLines : this.options.scaleShowHorizontalLines,
|
||||
showVerticalLines : this.options.scaleShowVerticalLines,
|
||||
gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
|
||||
gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
|
||||
padding : (this.options.showScale) ? 0 : this.options.borderWidth,
|
||||
showLabels : this.options.scaleShowLabels,
|
||||
display : this.options.showScale
|
||||
};
|
||||
this.eachElement(function(bar, index, dataset, datasetIndex) {
|
||||
helpers.extend(bar, {
|
||||
width: this.scale.calculateBarWidth(this.data.datasets.length),
|
||||
x: this.scale.calculateBarX(this.data.datasets.length, datasetIndex, index),
|
||||
y: this.scale.calculateY(this.data.datasets[datasetIndex].data[index]),
|
||||
value: this.data.datasets[datasetIndex].data[index],
|
||||
label: this.data.labels[index],
|
||||
datasetLabel: this.data.datasets[datasetIndex].label,
|
||||
borderColor: this.data.datasets[datasetIndex].borderColor,
|
||||
borderWidth: this.data.datasets[datasetIndex].borderWidth,
|
||||
backgroundColor: this.data.datasets[datasetIndex].backgroundColor,
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
});
|
||||
bar.pivot();
|
||||
}, this);
|
||||
|
||||
if (this.options.scaleOverride){
|
||||
helpers.extend(scaleOptions, {
|
||||
calculateYRange: helpers.noop,
|
||||
steps: this.options.scaleSteps,
|
||||
stepValue: this.options.scaleStepWidth,
|
||||
min: this.options.scaleStartValue,
|
||||
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
|
||||
});
|
||||
}
|
||||
this.render();
|
||||
},
|
||||
buildScale: function(labels) {
|
||||
var self = this;
|
||||
|
||||
this.scale = new this.ScaleClass(scaleOptions);
|
||||
},
|
||||
// This should be incorportated into the init as something like a default value. "Reflow" seems like a weird word for a fredraw function
|
||||
redraw : function(){
|
||||
var base = this.calculateBaseY();
|
||||
this.eachElement(function(element, index, datasetIndex){
|
||||
helpers.extend(element,{
|
||||
y: base,
|
||||
base : base
|
||||
});
|
||||
});
|
||||
this.render();
|
||||
},
|
||||
draw : function(ease){
|
||||
var dataTotal = function() {
|
||||
var values = [];
|
||||
self.eachValue(function(value) {
|
||||
values.push(value);
|
||||
});
|
||||
return values;
|
||||
};
|
||||
|
||||
var easingDecimal = ease || 1;
|
||||
this.clear();
|
||||
var scaleOptions = {
|
||||
templateString: this.options.scaleLabel,
|
||||
height: this.chart.height,
|
||||
width: this.chart.width,
|
||||
ctx: this.chart.ctx,
|
||||
textColor: this.options.scaleFontColor,
|
||||
fontSize: this.options.scaleFontSize,
|
||||
fontStyle: this.options.scaleFontStyle,
|
||||
fontFamily: this.options.scaleFontFamily,
|
||||
valuesCount: labels.length,
|
||||
beginAtZero: this.options.scaleBeginAtZero,
|
||||
integersOnly: this.options.scaleIntegersOnly,
|
||||
calculateYRange: function(currentHeight) {
|
||||
var updatedRanges = helpers.calculateScaleRange(
|
||||
dataTotal(),
|
||||
currentHeight,
|
||||
this.fontSize,
|
||||
this.beginAtZero,
|
||||
this.integersOnly
|
||||
);
|
||||
helpers.extend(this, updatedRanges);
|
||||
},
|
||||
xLabels: labels,
|
||||
font: helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
|
||||
lineWidth: this.options.scaleLineWidth,
|
||||
lineColor: this.options.scaleLineColor,
|
||||
showHorizontalLines: this.options.scaleShowHorizontalLines,
|
||||
showVerticalLines: this.options.scaleShowVerticalLines,
|
||||
gridLineWidth: (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
|
||||
gridLineColor: (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
|
||||
padding: (this.options.showScale) ? 0 : this.options.borderWidth,
|
||||
showLabels: this.options.scaleShowLabels,
|
||||
display: this.options.showScale
|
||||
};
|
||||
|
||||
this.scale.draw(easingDecimal);
|
||||
if (this.options.scaleOverride) {
|
||||
helpers.extend(scaleOptions, {
|
||||
calculateYRange: helpers.noop,
|
||||
steps: this.options.scaleSteps,
|
||||
stepValue: this.options.scaleStepWidth,
|
||||
min: this.options.scaleStartValue,
|
||||
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
|
||||
});
|
||||
}
|
||||
|
||||
//Draw all the bars for each dataset
|
||||
this.eachElement(function(bar, index, datasetIndex){
|
||||
if (bar.hasValue()){
|
||||
// Update the bar basepoint
|
||||
bar.base = this.calculateBaseY();
|
||||
//Transition
|
||||
bar.transition(easingDecimal).draw();
|
||||
}
|
||||
}, this);
|
||||
this.scale = new this.ScaleClass(scaleOptions);
|
||||
},
|
||||
// This should be incorportated into the init as something like a default value. "Reflow" seems like a weird word for a fredraw function
|
||||
redraw: function() {
|
||||
var base = this.calculateBaseY();
|
||||
this.eachElement(function(element, index, datasetIndex) {
|
||||
helpers.extend(element, {
|
||||
y: base,
|
||||
base: base
|
||||
});
|
||||
});
|
||||
this.render();
|
||||
},
|
||||
draw: function(ease) {
|
||||
|
||||
// Finally draw the tooltip
|
||||
this.tooltip.transition(easingDecimal).draw();
|
||||
}
|
||||
});
|
||||
var easingDecimal = ease || 1;
|
||||
this.clear();
|
||||
|
||||
this.scale.draw(easingDecimal);
|
||||
|
||||
//Draw all the bars for each dataset
|
||||
this.eachElement(function(bar, index, datasetIndex) {
|
||||
if (bar.hasValue()) {
|
||||
// Update the bar basepoint
|
||||
bar.base = this.calculateBaseY();
|
||||
//Transition
|
||||
bar.transition(easingDecimal).draw();
|
||||
}
|
||||
}, this);
|
||||
|
||||
// Finally draw the tooltip
|
||||
this.tooltip.transition(easingDecimal).draw();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}).call(this);
|
||||
|
||||
4570
src/Chart.Core.js
4570
src/Chart.Core.js
File diff suppressed because it is too large
Load Diff
@@ -1,212 +1,319 @@
|
||||
(function(){
|
||||
"use strict";
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
var root = this,
|
||||
Chart = root.Chart,
|
||||
//Cache a local reference to Chart.helpers
|
||||
helpers = Chart.helpers;
|
||||
var root = this,
|
||||
Chart = root.Chart,
|
||||
//Cache a local reference to Chart.helpers
|
||||
helpers = Chart.helpers;
|
||||
|
||||
var defaultConfig = {
|
||||
//Boolean - Whether we should show a stroke on each segment
|
||||
segmentShowStroke : true,
|
||||
var defaultConfig = {
|
||||
//Boolean - Whether we should show a stroke on each segment
|
||||
segmentShowStroke: true,
|
||||
|
||||
//String - The colour of each segment stroke
|
||||
segmentStrokeColor : "#fff",
|
||||
//String - The colour of each segment stroke
|
||||
segmentStrokeColor: "#fff",
|
||||
|
||||
//Number - The width of each segment stroke
|
||||
segmentStrokeWidth : 2,
|
||||
//Number - The width of each segment stroke
|
||||
segmentStrokeWidth: 2,
|
||||
|
||||
//The percentage of the chart that we cut out of the middle.
|
||||
percentageInnerCutout : 50,
|
||||
//The percentage of the chart that we cut out of the middle.
|
||||
percentageInnerCutout: 50,
|
||||
|
||||
//Number - Amount of animation steps
|
||||
animationSteps : 100,
|
||||
//Number - Amount of animation steps
|
||||
animationSteps: 100,
|
||||
|
||||
//String - Animation easing effect
|
||||
animationEasing : "easeOutBounce",
|
||||
//String - Animation easing effect
|
||||
animationEasing: "easeOutBounce",
|
||||
|
||||
//Boolean - Whether we animate the rotation of the Doughnut
|
||||
animateRotate : true,
|
||||
//Boolean - Whether we animate the rotation of the Doughnut
|
||||
animateRotate: true,
|
||||
|
||||
//Boolean - Whether we animate scaling the Doughnut from the centre
|
||||
animateScale : false,
|
||||
//Boolean - Whether we animate scaling the Doughnut from the centre
|
||||
animateScale: false,
|
||||
|
||||
//String - A legend template
|
||||
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
|
||||
//String - A legend template
|
||||
legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].backgroundColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
Chart.Type.extend({
|
||||
//Passing in a name registers this chart in the Chart namespace
|
||||
name: "Doughnut",
|
||||
//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(data){
|
||||
Chart.Type.extend({
|
||||
//Passing in a name registers this chart in the Chart namespace
|
||||
name: "Doughnut",
|
||||
//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(data) {
|
||||
|
||||
// Save data as a source for updating of values & methods
|
||||
this.data = data;
|
||||
// Save data as a source for updating of values & methods
|
||||
this.data = data;
|
||||
|
||||
//Declare segments as a static property to prevent inheriting across the Chart type prototype
|
||||
this.segments = [];
|
||||
this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
|
||||
// Slice Type and defaults
|
||||
this.Slice = Chart.Arc.extend({
|
||||
_chart: this.chart,
|
||||
x: this.chart.width / 2,
|
||||
y: this.chart.height / 2
|
||||
});
|
||||
|
||||
this.SegmentArc = Chart.Arc.extend({
|
||||
ctx : this.chart.ctx,
|
||||
x : this.chart.width/2,
|
||||
y : this.chart.height/2
|
||||
});
|
||||
//Set up tooltip events on the chart
|
||||
if (this.options.showTooltips) {
|
||||
helpers.bindEvents(this, this.options.tooltipEvents, this.onHover);
|
||||
}
|
||||
this.calculateTotal(data);
|
||||
|
||||
//Set up tooltip events on the chart
|
||||
if (this.options.showTooltips){
|
||||
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
|
||||
var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
|
||||
// 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);
|
||||
|
||||
helpers.each(this.segments,function(segment){
|
||||
segment.restore(["fillColor"]);
|
||||
});
|
||||
helpers.each(activeSegments,function(activeSegment){
|
||||
activeSegment.fillColor = activeSegment.highlightColor;
|
||||
});
|
||||
this.showTooltip(activeSegments);
|
||||
});
|
||||
}
|
||||
this.calculateTotal(data);
|
||||
// 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);
|
||||
|
||||
helpers.each(data,function(datapoint, index){
|
||||
if (!datapoint.color) {
|
||||
datapoint.color = 'hsl(' + (360 * index / data.length) + ', 100%, 50%)';
|
||||
}
|
||||
this.addData(datapoint, index, true);
|
||||
},this);
|
||||
this.update();
|
||||
},
|
||||
onHover: function(evt) {
|
||||
|
||||
this.render();
|
||||
},
|
||||
getSegmentsAtEvent : function(e){
|
||||
var segmentsArray = [];
|
||||
// If exiting chart
|
||||
if (e.type == 'mouseout') {
|
||||
return this;
|
||||
}
|
||||
|
||||
var location = helpers.getRelativePosition(e);
|
||||
this.lastActive = this.lastActive || [];
|
||||
|
||||
helpers.each(this.segments,function(segment){
|
||||
if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
|
||||
},this);
|
||||
return segmentsArray;
|
||||
},
|
||||
addData : function(segment, atIndex, silent){
|
||||
var index = atIndex || this.segments.length;
|
||||
this.segments.splice(index, 0, new this.SegmentArc({
|
||||
value : segment.value,
|
||||
outerRadius : (this.options.animateScale) ? 0 : this.outerRadius,
|
||||
innerRadius : (this.options.animateScale) ? 0 : (this.outerRadius/100) * this.options.percentageInnerCutout,
|
||||
fillColor : segment.color,
|
||||
highlightColor : segment.highlight || segment.color,
|
||||
showStroke : this.options.segmentShowStroke,
|
||||
strokeWidth : this.options.segmentStrokeWidth,
|
||||
strokeColor : this.options.segmentStrokeColor,
|
||||
startAngle : Math.PI * 1.5,
|
||||
circumference : (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value),
|
||||
label : segment.label
|
||||
}));
|
||||
if (!silent){
|
||||
this.reflow();
|
||||
this.update();
|
||||
}
|
||||
},
|
||||
calculateCircumference : function(value) {
|
||||
if ( this.total > 0 ) {
|
||||
return (Math.PI*2)*(value / this.total);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
calculateTotal : function(data){
|
||||
this.total = 0;
|
||||
helpers.each(data,function(segment){
|
||||
this.total += Math.abs(segment.value);
|
||||
},this);
|
||||
},
|
||||
update : function(){
|
||||
// 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);
|
||||
|
||||
// Map new data to data points
|
||||
if(this.data.length == this.segments.length){
|
||||
helpers.each(this.data, function(segment, i){
|
||||
helpers.extend(this.segments[i], {
|
||||
value : segment.value,
|
||||
fillColor : segment.color,
|
||||
highlightColor : segment.highlight || segment.color,
|
||||
showStroke : this.options.segmentShowStroke,
|
||||
strokeWidth : this.options.segmentStrokeWidth,
|
||||
strokeColor : this.options.segmentStrokeColor,
|
||||
label : segment.label
|
||||
});
|
||||
}, this);
|
||||
} else{
|
||||
// Data size changed without properly inserting, just redraw the chart
|
||||
this.initialize(this.data);
|
||||
}
|
||||
// On Hover hook
|
||||
if (this.options.onHover) {
|
||||
this.options.onHover.call(this, this.active);
|
||||
}
|
||||
|
||||
this.calculateTotal(this.segments);
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
// Reset any highlight colours before updating.
|
||||
helpers.each(this.activeElements, function(activeElement){
|
||||
activeElement.restore(['fillColor']);
|
||||
});
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
helpers.each(this.segments,function(segment){
|
||||
segment.save();
|
||||
});
|
||||
this.render();
|
||||
},
|
||||
|
||||
removeData: function(atIndex){
|
||||
var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
|
||||
this.segments.splice(indexToDelete, 1);
|
||||
this.reflow();
|
||||
this.update();
|
||||
},
|
||||
// Built in Tooltips
|
||||
if (this.options.showTooltips) {
|
||||
|
||||
reflow : function(){
|
||||
helpers.extend(this.SegmentArc.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);
|
||||
},
|
||||
draw : function(easeDecimal){
|
||||
var animDecimal = (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);
|
||||
// The usual updates
|
||||
this.tooltip.initialize();
|
||||
|
||||
segment.endAngle = segment.startAngle + segment.circumference;
|
||||
// Active
|
||||
if (this.active.length) {
|
||||
helpers.extend(this.tooltip, {
|
||||
opacity: 1,
|
||||
_active: this.active,
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
},this);
|
||||
this.tooltip.update();
|
||||
} else {
|
||||
// Inactive
|
||||
helpers.extend(this.tooltip, {
|
||||
opacity: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
Chart.types.Doughnut.extend({
|
||||
name : "Pie",
|
||||
defaults : helpers.merge(defaultConfig,{percentageInnerCutout : 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.hoverAnimationDuration);
|
||||
}
|
||||
}
|
||||
|
||||
// Remember Last Active
|
||||
this.lastActive = this.active;
|
||||
return this;
|
||||
|
||||
},
|
||||
getSegmentsAtEvent: function(e) {
|
||||
var segmentsArray = [];
|
||||
|
||||
var location = helpers.getRelativePosition(e);
|
||||
|
||||
helpers.each(this.segments, function(segment) {
|
||||
if (segment.inRange(location.x, location.y)) segmentsArray.push(segment);
|
||||
}, this);
|
||||
return segmentsArray;
|
||||
},
|
||||
calculateCircumference: function(value) {
|
||||
if (this.total > 0) {
|
||||
return (Math.PI * 2) * (value / this.total);
|
||||
} else {
|
||||
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;
|
||||
|
||||
|
||||
// Map new data to data points
|
||||
helpers.each(this.data, function(segment, i) {
|
||||
helpers.extend(this.segments[i], {
|
||||
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,
|
||||
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);
|
||||
|
||||
// Reset any highlight colours before updating.
|
||||
helpers.each(this.activeElements, function(activeElement) {
|
||||
activeElement.restore(['backgroundColor']);
|
||||
});
|
||||
|
||||
helpers.each(this.segments, function(segment) {
|
||||
segment.save();
|
||||
});
|
||||
this.render();
|
||||
},
|
||||
|
||||
removeData: function(atIndex) {
|
||||
var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length - 1;
|
||||
this.segments.splice(indexToDelete, 1);
|
||||
this.reflow();
|
||||
this.update();
|
||||
},
|
||||
|
||||
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);
|
||||
},
|
||||
draw: function(easeDecimal) {
|
||||
var animDecimal = (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;
|
||||
}
|
||||
}, this);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
Chart.types.Doughnut.extend({
|
||||
name: "Pie",
|
||||
defaults: helpers.merge(defaultConfig, {
|
||||
percentageInnerCutout: 0
|
||||
})
|
||||
});
|
||||
|
||||
}).call(this);
|
||||
|
||||
@@ -1,427 +1,423 @@
|
||||
(function(){
|
||||
"use strict";
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
var root = this,
|
||||
Chart = root.Chart,
|
||||
helpers = Chart.helpers;
|
||||
var root = this,
|
||||
Chart = root.Chart,
|
||||
helpers = Chart.helpers;
|
||||
|
||||
var defaultConfig = {
|
||||
var defaultConfig = {
|
||||
|
||||
///Boolean - Whether grid lines are shown across the chart
|
||||
scaleShowGridLines : true,
|
||||
///Boolean - Whether grid lines are shown across the chart
|
||||
scaleShowGridLines: true,
|
||||
|
||||
//String - Colour of the grid lines
|
||||
scaleGridLineColor : "rgba(0,0,0,.05)",
|
||||
//String - Colour of the grid lines
|
||||
scaleGridLineColor: "rgba(0,0,0,.05)",
|
||||
|
||||
//Number - Width of the grid lines
|
||||
scaleGridLineWidth : 1,
|
||||
//Number - Width of the grid lines
|
||||
scaleGridLineWidth: 1,
|
||||
|
||||
//Boolean - Whether to show horizontal lines (except X axis)
|
||||
scaleShowHorizontalLines: true,
|
||||
//Boolean - Whether to show horizontal lines (except X axis)
|
||||
scaleShowHorizontalLines: true,
|
||||
|
||||
//Boolean - Whether to show vertical lines (except Y axis)
|
||||
scaleShowVerticalLines: true,
|
||||
//Boolean - Whether to show vertical lines (except Y axis)
|
||||
scaleShowVerticalLines: true,
|
||||
|
||||
//Number - Tension of the bezier curve between points
|
||||
tension : 0.4,
|
||||
//Number - Tension of the bezier curve between points
|
||||
tension: 0.4,
|
||||
|
||||
//Number - Radius of each point dot in pixels
|
||||
pointRadius : 4,
|
||||
//Number - Radius of each point dot in pixels
|
||||
pointRadius: 4,
|
||||
|
||||
//Number - Pixel width of point dot border
|
||||
pointBorderWidth : 1,
|
||||
//Number - Pixel width of point dot border
|
||||
pointBorderWidth: 1,
|
||||
|
||||
//Number - amount extra to add to the radius to cater for hit detection outside the drawn point
|
||||
pointHoverRadius : 20,
|
||||
//Number - amount extra to add to the radius to cater for hit detection outside the drawn point
|
||||
pointHoverRadius: 20,
|
||||
|
||||
//Number - Pixel width of dataset border
|
||||
borderWidth : 2,
|
||||
//Number - Pixel width of dataset border
|
||||
borderWidth: 2,
|
||||
|
||||
//String - A legend template
|
||||
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].borderColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>",
|
||||
//String - A legend template
|
||||
legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].borderColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>",
|
||||
|
||||
//Boolean - Whether to horizontally center the label and point dot inside the grid
|
||||
offsetGridLines : false
|
||||
//Boolean - Whether to horizontally center the label and point dot inside the grid
|
||||
offsetGridLines: false
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Chart.Type.extend({
|
||||
name: "Line",
|
||||
defaults : defaultConfig,
|
||||
initialize: function(data){
|
||||
// Save data as a source for updating of values & methods
|
||||
this.data = data;
|
||||
Chart.Type.extend({
|
||||
name: "Line",
|
||||
defaults: defaultConfig,
|
||||
initialize: function(data) {
|
||||
// Save data as a source for updating of values & methods
|
||||
this.data = data;
|
||||
|
||||
//Custom Point Defaults
|
||||
this.PointClass = Chart.Point.extend({
|
||||
_chart: this.chart,
|
||||
offsetGridLines : this.options.offsetGridLines,
|
||||
borderWidth : this.options.pointBorderWidth,
|
||||
radius : this.options.pointRadius,
|
||||
hoverRadius : this.options.pointHoverRadius,
|
||||
});
|
||||
//Custom Point Defaults
|
||||
this.PointClass = Chart.Point.extend({
|
||||
_chart: this.chart,
|
||||
offsetGridLines: this.options.offsetGridLines,
|
||||
borderWidth: this.options.pointBorderWidth,
|
||||
radius: this.options.pointRadius,
|
||||
hoverRadius: this.options.pointHoverRadius,
|
||||
});
|
||||
|
||||
// Events
|
||||
helpers.bindEvents(this, this.options.tooltipEvents, this.onHover);
|
||||
// Events
|
||||
helpers.bindEvents(this, this.options.tooltipEvents, this.onHover);
|
||||
|
||||
// Build Scale
|
||||
this.buildScale(this.data.labels);
|
||||
// Build Scale
|
||||
this.buildScale(this.data.labels);
|
||||
|
||||
|
||||
//Create a new line and its points for each dataset and piece of data
|
||||
helpers.each(this.data.datasets,function(dataset,datasetIndex){
|
||||
dataset.metaDataset = new Chart.Line();
|
||||
dataset.metaData = [];
|
||||
helpers.each(dataset.data,function(dataPoint,index){
|
||||
dataset.metaData.push(new this.PointClass());
|
||||
},this);
|
||||
},this);
|
||||
//Create a new line and its points for each dataset and piece of data
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
dataset.metaDataset = new Chart.Line();
|
||||
dataset.metaData = [];
|
||||
helpers.each(dataset.data, function(dataPoint, index) {
|
||||
dataset.metaData.push(new this.PointClass());
|
||||
}, this);
|
||||
}, this);
|
||||
|
||||
// Set defaults for lines
|
||||
this.eachDataset(function(dataset, datasetIndex){
|
||||
dataset = helpers.merge(this.options, dataset);
|
||||
helpers.extend(dataset.metaDataset, {
|
||||
_points: dataset.metaData,
|
||||
_datasetIndex: datasetIndex,
|
||||
_chart: this.chart,
|
||||
});
|
||||
// Copy to view model
|
||||
dataset.metaDataset.save();
|
||||
}, this);
|
||||
// Set defaults for lines
|
||||
this.eachDataset(function(dataset, datasetIndex) {
|
||||
dataset = helpers.merge(this.options, dataset);
|
||||
helpers.extend(dataset.metaDataset, {
|
||||
_points: dataset.metaData,
|
||||
_datasetIndex: datasetIndex,
|
||||
_chart: this.chart,
|
||||
});
|
||||
// Copy to view model
|
||||
dataset.metaDataset.save();
|
||||
}, this);
|
||||
|
||||
// Set defaults for points
|
||||
this.eachElement(function(point, index, dataset, datasetIndex){
|
||||
helpers.extend(point, {
|
||||
x: this.scale.calculateX(index),
|
||||
y: this.scale.endPoint,
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
_chart: this.chart
|
||||
});
|
||||
// Set defaults for points
|
||||
this.eachElement(function(point, index, dataset, datasetIndex) {
|
||||
helpers.extend(point, {
|
||||
x: this.scale.calculateX(index),
|
||||
y: this.scale.endPoint,
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
_chart: this.chart
|
||||
});
|
||||
|
||||
// Default bezier control points
|
||||
helpers.extend(point, {
|
||||
controlPointPreviousX: this.previousPoint(dataset, index).x,
|
||||
controlPointPreviousY: this.nextPoint(dataset, index).y,
|
||||
controlPointNextX: this.previousPoint(dataset, index).x,
|
||||
controlPointNextY: this.nextPoint(dataset, index).y,
|
||||
});
|
||||
// Copy to view model
|
||||
point.save();
|
||||
}, this);
|
||||
// Default bezier control points
|
||||
helpers.extend(point, {
|
||||
controlPointPreviousX: this.previousPoint(dataset, index).x,
|
||||
controlPointPreviousY: this.nextPoint(dataset, index).y,
|
||||
controlPointNextX: this.previousPoint(dataset, index).x,
|
||||
controlPointNextY: this.nextPoint(dataset, index).y,
|
||||
});
|
||||
// Copy to view model
|
||||
point.save();
|
||||
}, 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);
|
||||
// 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);
|
||||
|
||||
this.update();
|
||||
},
|
||||
nextPoint: function(collection, index){
|
||||
return collection[index - 1] || collection[index];
|
||||
},
|
||||
previousPoint: function(collection, index){
|
||||
return collection[index + 1] || collection[index];
|
||||
},
|
||||
onHover: function(e){
|
||||
this.update();
|
||||
},
|
||||
nextPoint: function(collection, index) {
|
||||
return collection[index - 1] || collection[index];
|
||||
},
|
||||
previousPoint: function(collection, index) {
|
||||
return collection[index + 1] || collection[index];
|
||||
},
|
||||
onHover: function(e) {
|
||||
|
||||
|
||||
// If exiting chart
|
||||
if(e.type == 'mouseout'){
|
||||
return this;
|
||||
}
|
||||
// If exiting chart
|
||||
if (e.type == 'mouseout') {
|
||||
return this;
|
||||
}
|
||||
|
||||
this.lastActive = this.lastActive || [];
|
||||
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);
|
||||
// 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);
|
||||
|
||||
// On Hover hook
|
||||
if(this.options.onHover){
|
||||
this.options.onHover.call(this, this.active);
|
||||
}
|
||||
// On Hover hook
|
||||
if (this.options.onHover) {
|
||||
this.options.onHover.call(this, this.active);
|
||||
}
|
||||
|
||||
// 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[this.lastActive[0]._datasetIndex].pointBackgroundColor;
|
||||
this.lastActive[0].borderColor = this.data.datasets[this.lastActive[0]._datasetIndex].pointBorderColor;
|
||||
this.lastActive[0].borderWidth = this.data.datasets[this.lastActive[0]._datasetIndex].pointBorderWidth;
|
||||
break;
|
||||
case 'label':
|
||||
for (var i = 0; i < this.lastActive.length; i++) {
|
||||
this.lastActive[i].backgroundColor = this.data.datasets[this.lastActive[i]._datasetIndex].pointBackgroundColor;
|
||||
this.lastActive[i].borderColor = this.data.datasets[this.lastActive[i]._datasetIndex].pointBorderColor;
|
||||
this.lastActive[i].borderWidth = this.data.datasets[this.lastActive[0]._datasetIndex].pointBorderWidth;
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
this.active[0].borderColor = this.data.datasets[this.active[0]._datasetIndex].hoverBorderColor || helpers.color(this.active[0].borderColor).saturate(0.5).darken(0.35).rgbString();
|
||||
this.active[0].borderWidth = this.data.datasets[this.active[0]._datasetIndex].borderWidth + 10;
|
||||
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();
|
||||
this.active[i].borderColor = this.data.datasets[this.active[i]._datasetIndex].hoverBorderColor || helpers.color(this.active[i].borderColor).saturate(0.5).darken(0.35).rgbString();
|
||||
this.active[i].borderWidth = this.data.datasets[this.active[i]._datasetIndex].borderWidth + 2;
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
// 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[this.lastActive[0]._datasetIndex].pointBackgroundColor;
|
||||
this.lastActive[0].borderColor = this.data.datasets[this.lastActive[0]._datasetIndex].pointBorderColor;
|
||||
this.lastActive[0].borderWidth = this.data.datasets[this.lastActive[0]._datasetIndex].pointBorderWidth;
|
||||
break;
|
||||
case 'label':
|
||||
for (var i = 0; i < this.lastActive.length; i++) {
|
||||
this.lastActive[i].backgroundColor = this.data.datasets[this.lastActive[i]._datasetIndex].pointBackgroundColor;
|
||||
this.lastActive[i].borderColor = this.data.datasets[this.lastActive[i]._datasetIndex].pointBorderColor;
|
||||
this.lastActive[i].borderWidth = this.data.datasets[this.lastActive[0]._datasetIndex].pointBorderWidth;
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
this.active[0].borderColor = this.data.datasets[this.active[0]._datasetIndex].hoverBorderColor || helpers.color(this.active[0].borderColor).saturate(0.5).darken(0.35).rgbString();
|
||||
this.active[0].borderWidth = this.data.datasets[this.active[0]._datasetIndex].borderWidth + 10;
|
||||
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();
|
||||
this.active[i].borderColor = this.data.datasets[this.active[i]._datasetIndex].hoverBorderColor || helpers.color(this.active[i].borderColor).saturate(0.5).darken(0.35).rgbString();
|
||||
this.active[i].borderWidth = this.data.datasets[this.active[i]._datasetIndex].borderWidth + 2;
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Built in Tooltips
|
||||
if(this.options.showTooltips){
|
||||
// Built in Tooltips
|
||||
if (this.options.showTooltips) {
|
||||
|
||||
// The usual updates
|
||||
this.tooltip.initialize();
|
||||
// The usual updates
|
||||
this.tooltip.initialize();
|
||||
|
||||
// Active
|
||||
if(this.active.length){
|
||||
helpers.extend(this.tooltip, {
|
||||
opacity: 1,
|
||||
_active: this.active,
|
||||
});
|
||||
// Active
|
||||
if (this.active.length) {
|
||||
helpers.extend(this.tooltip, {
|
||||
opacity: 1,
|
||||
_active: this.active,
|
||||
});
|
||||
|
||||
this.tooltip.update();
|
||||
}
|
||||
else{
|
||||
// Inactive
|
||||
helpers.extend(this.tooltip, {
|
||||
opacity: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
this.tooltip.update();
|
||||
} else {
|
||||
// Inactive
|
||||
helpers.extend(this.tooltip, {
|
||||
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);
|
||||
// Hover animations
|
||||
this.tooltip.pivot();
|
||||
|
||||
// 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)){
|
||||
if (!this.animating) {
|
||||
var changed;
|
||||
|
||||
this.stop();
|
||||
this.render(this.options.hoverAnimationDuration);
|
||||
}
|
||||
}
|
||||
helpers.each(this.active, function(element, index) {
|
||||
if (element !== this.lastActive[index]) {
|
||||
changed = true;
|
||||
}
|
||||
}, this);
|
||||
|
||||
// Remember Last Active
|
||||
this.lastActive = this.active;
|
||||
return this;
|
||||
},
|
||||
update : function(){
|
||||
// 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.scale.update();
|
||||
this.stop();
|
||||
this.render(this.options.hoverAnimationDuration);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the lines
|
||||
this.eachDataset(function(dataset, datasetIndex){
|
||||
helpers.extend(dataset.metaDataset, {
|
||||
backgroundColor: dataset.backgroundColor || this.options.backgroundColor,
|
||||
borderWidth: dataset.borderWidth || this.options.borderWidth,
|
||||
borderColor: dataset.borderColor || this.options.borderColor,
|
||||
tension: dataset.tension || this.options.tension,
|
||||
scaleTop: this.scale.startPoint,
|
||||
scaleBottom: this.scale.endPoint,
|
||||
_points: dataset.metaData,
|
||||
_datasetIndex: datasetIndex,
|
||||
});
|
||||
dataset.metaDataset.pivot();
|
||||
});
|
||||
// Remember Last Active
|
||||
this.lastActive = this.active;
|
||||
return this;
|
||||
|
||||
// Update the points
|
||||
this.eachElement(function(point, index, dataset, datasetIndex){
|
||||
helpers.extend(point, {
|
||||
x: this.scale.calculateX(index),
|
||||
y: this.scale.calculateY(this.data.datasets[datasetIndex].data[index]),
|
||||
value : this.data.datasets[datasetIndex].data[index],
|
||||
label : this.data.labels[index],
|
||||
datasetLabel: this.data.datasets[datasetIndex].label,
|
||||
// Appearance
|
||||
hoverBackgroundColor: this.data.datasets[datasetIndex].pointHoverBackgroundColor || this.options.pointHoverBackgroundColor,
|
||||
hoverBorderColor : this.data.datasets[datasetIndex].pointHoverBorderColor || this.options.pointHoverBorderColor,
|
||||
hoverRadius : this.data.datasets[datasetIndex].pointHoverRadius || this.options.pointHoverRadius,
|
||||
radius: this.data.datasets[datasetIndex].pointRadius || this.options.pointRadius,
|
||||
borderWidth: this.data.datasets[datasetIndex].pointBorderWidth || this.options.pointBorderWidth,
|
||||
borderColor: this.data.datasets[datasetIndex].pointBorderColor || this.options.pointBorderColor,
|
||||
backgroundColor: this.data.datasets[datasetIndex].pointBackgroundColor || this.options.pointBackgroundColor,
|
||||
tension: this.data.datasets[datasetIndex].metaDataset.tension,
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
});
|
||||
}, this);
|
||||
},
|
||||
update: function() {
|
||||
|
||||
// Update control points for the bezier curve
|
||||
this.eachElement(function(point, index, dataset, datasetIndex){
|
||||
var controlPoints = helpers.splineCurve(
|
||||
this.previousPoint(dataset, index),
|
||||
point,
|
||||
this.nextPoint(dataset, index),
|
||||
point.tension
|
||||
);
|
||||
this.scale.update();
|
||||
|
||||
point.controlPointPreviousX = controlPoints.previous.x;
|
||||
point.controlPointNextX = controlPoints.next.x;
|
||||
// Update the lines
|
||||
this.eachDataset(function(dataset, datasetIndex) {
|
||||
helpers.extend(dataset.metaDataset, {
|
||||
backgroundColor: dataset.backgroundColor || this.options.backgroundColor,
|
||||
borderWidth: dataset.borderWidth || this.options.borderWidth,
|
||||
borderColor: dataset.borderColor || this.options.borderColor,
|
||||
tension: dataset.tension || this.options.tension,
|
||||
scaleTop: this.scale.startPoint,
|
||||
scaleBottom: this.scale.endPoint,
|
||||
_points: dataset.metaData,
|
||||
_datasetIndex: datasetIndex,
|
||||
});
|
||||
dataset.metaDataset.pivot();
|
||||
});
|
||||
|
||||
// Prevent the bezier going outside of the bounds of the graph
|
||||
// Update the points
|
||||
this.eachElement(function(point, index, dataset, datasetIndex) {
|
||||
helpers.extend(point, {
|
||||
x: this.scale.calculateX(index),
|
||||
y: this.scale.calculateY(this.data.datasets[datasetIndex].data[index]),
|
||||
value: this.data.datasets[datasetIndex].data[index],
|
||||
label: this.data.labels[index],
|
||||
datasetLabel: this.data.datasets[datasetIndex].label,
|
||||
// Appearance
|
||||
hoverBackgroundColor: this.data.datasets[datasetIndex].pointHoverBackgroundColor || this.options.pointHoverBackgroundColor,
|
||||
hoverBorderColor: this.data.datasets[datasetIndex].pointHoverBorderColor || this.options.pointHoverBorderColor,
|
||||
hoverRadius: this.data.datasets[datasetIndex].pointHoverRadius || this.options.pointHoverRadius,
|
||||
radius: this.data.datasets[datasetIndex].pointRadius || this.options.pointRadius,
|
||||
borderWidth: this.data.datasets[datasetIndex].pointBorderWidth || this.options.pointBorderWidth,
|
||||
borderColor: this.data.datasets[datasetIndex].pointBorderColor || this.options.pointBorderColor,
|
||||
backgroundColor: this.data.datasets[datasetIndex].pointBackgroundColor || this.options.pointBackgroundColor,
|
||||
tension: this.data.datasets[datasetIndex].metaDataset.tension,
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
});
|
||||
}, this);
|
||||
|
||||
// Cap puter bezier handles to the upper/lower scale bounds
|
||||
if (controlPoints.next.y > this.scale.endPoint){
|
||||
point.controlPointNextY = this.scale.endPoint;
|
||||
}
|
||||
else if (controlPoints.next.y < this.scale.startPoint){
|
||||
point.controlPointNextY = this.scale.startPoint;
|
||||
}
|
||||
else{
|
||||
point.controlPointNextY = controlPoints.next.y;
|
||||
}
|
||||
// Update control points for the bezier curve
|
||||
this.eachElement(function(point, index, dataset, datasetIndex) {
|
||||
var controlPoints = helpers.splineCurve(
|
||||
this.previousPoint(dataset, index),
|
||||
point,
|
||||
this.nextPoint(dataset, index),
|
||||
point.tension
|
||||
);
|
||||
|
||||
// Cap inner bezier handles to the upper/lower scale bounds
|
||||
if (controlPoints.previous.y > this.scale.endPoint){
|
||||
point.controlPointPreviousY = this.scale.endPoint;
|
||||
}
|
||||
else if (controlPoints.previous.y < this.scale.startPoint){
|
||||
point.controlPointPreviousY = this.scale.startPoint;
|
||||
}
|
||||
else{
|
||||
point.controlPointPreviousY = controlPoints.previous.y;
|
||||
}
|
||||
// Now pivot the point for animation
|
||||
point.pivot();
|
||||
}, this);
|
||||
point.controlPointPreviousX = controlPoints.previous.x;
|
||||
point.controlPointNextX = controlPoints.next.x;
|
||||
|
||||
this.render();
|
||||
},
|
||||
buildScale : function(labels){
|
||||
var self = this;
|
||||
// Prevent the bezier going outside of the bounds of the graph
|
||||
|
||||
var dataTotal = function(){
|
||||
var values = [];
|
||||
self.eachValue(function(value){
|
||||
values.push(value);
|
||||
});
|
||||
// Cap puter bezier handles to the upper/lower scale bounds
|
||||
if (controlPoints.next.y > this.scale.endPoint) {
|
||||
point.controlPointNextY = this.scale.endPoint;
|
||||
} else if (controlPoints.next.y < this.scale.startPoint) {
|
||||
point.controlPointNextY = this.scale.startPoint;
|
||||
} else {
|
||||
point.controlPointNextY = controlPoints.next.y;
|
||||
}
|
||||
|
||||
return values;
|
||||
};
|
||||
// Cap inner bezier handles to the upper/lower scale bounds
|
||||
if (controlPoints.previous.y > this.scale.endPoint) {
|
||||
point.controlPointPreviousY = this.scale.endPoint;
|
||||
} else if (controlPoints.previous.y < this.scale.startPoint) {
|
||||
point.controlPointPreviousY = this.scale.startPoint;
|
||||
} else {
|
||||
point.controlPointPreviousY = controlPoints.previous.y;
|
||||
}
|
||||
// Now pivot the point for animation
|
||||
point.pivot();
|
||||
}, this);
|
||||
|
||||
var scaleOptions = {
|
||||
templateString : this.options.scaleLabel,
|
||||
height : this.chart.height,
|
||||
width : this.chart.width,
|
||||
ctx : this.chart.ctx,
|
||||
textColor : this.options.scaleFontColor,
|
||||
offsetGridLines : this.options.offsetGridLines,
|
||||
fontSize : this.options.scaleFontSize,
|
||||
fontStyle : this.options.scaleFontStyle,
|
||||
fontFamily : this.options.scaleFontFamily,
|
||||
valuesCount : labels.length,
|
||||
beginAtZero : this.options.scaleBeginAtZero,
|
||||
integersOnly : this.options.scaleIntegersOnly,
|
||||
calculateYRange : function(currentHeight){
|
||||
var updatedRanges = helpers.calculateScaleRange(
|
||||
dataTotal(),
|
||||
currentHeight,
|
||||
this.fontSize,
|
||||
this.beginAtZero,
|
||||
this.integersOnly
|
||||
);
|
||||
helpers.extend(this, updatedRanges);
|
||||
},
|
||||
xLabels : this.data.labels,
|
||||
font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
|
||||
lineWidth : this.options.scaleLineWidth,
|
||||
lineColor : this.options.scaleLineColor,
|
||||
showHorizontalLines : this.options.scaleShowHorizontalLines,
|
||||
showVerticalLines : this.options.scaleShowVerticalLines,
|
||||
gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
|
||||
gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
|
||||
padding: (this.options.showScale) ? 0 : this.options.pointRadius + this.options.pointBorderWidth,
|
||||
showLabels : this.options.scaleShowLabels,
|
||||
display : this.options.showScale
|
||||
};
|
||||
this.render();
|
||||
},
|
||||
buildScale: function(labels) {
|
||||
var self = this;
|
||||
|
||||
if (this.options.scaleOverride){
|
||||
helpers.extend(scaleOptions, {
|
||||
calculateYRange: helpers.noop,
|
||||
steps: this.options.scaleSteps,
|
||||
stepValue: this.options.scaleStepWidth,
|
||||
min: this.options.scaleStartValue,
|
||||
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
|
||||
});
|
||||
}
|
||||
var dataTotal = function() {
|
||||
var values = [];
|
||||
self.eachValue(function(value) {
|
||||
values.push(value);
|
||||
});
|
||||
|
||||
this.scale = new Chart.Scale(scaleOptions);
|
||||
},
|
||||
redraw : function(){
|
||||
|
||||
},
|
||||
draw : function(ease){
|
||||
return values;
|
||||
};
|
||||
|
||||
var easingDecimal = ease || 1;
|
||||
this.clear();
|
||||
var scaleOptions = {
|
||||
templateString: this.options.scaleLabel,
|
||||
height: this.chart.height,
|
||||
width: this.chart.width,
|
||||
ctx: this.chart.ctx,
|
||||
textColor: this.options.scaleFontColor,
|
||||
offsetGridLines: this.options.offsetGridLines,
|
||||
fontSize: this.options.scaleFontSize,
|
||||
fontStyle: this.options.scaleFontStyle,
|
||||
fontFamily: this.options.scaleFontFamily,
|
||||
valuesCount: labels.length,
|
||||
beginAtZero: this.options.scaleBeginAtZero,
|
||||
integersOnly: this.options.scaleIntegersOnly,
|
||||
calculateYRange: function(currentHeight) {
|
||||
var updatedRanges = helpers.calculateScaleRange(
|
||||
dataTotal(),
|
||||
currentHeight,
|
||||
this.fontSize,
|
||||
this.beginAtZero,
|
||||
this.integersOnly
|
||||
);
|
||||
helpers.extend(this, updatedRanges);
|
||||
},
|
||||
xLabels: this.data.labels,
|
||||
font: helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
|
||||
lineWidth: this.options.scaleLineWidth,
|
||||
lineColor: this.options.scaleLineColor,
|
||||
showHorizontalLines: this.options.scaleShowHorizontalLines,
|
||||
showVerticalLines: this.options.scaleShowVerticalLines,
|
||||
gridLineWidth: (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
|
||||
gridLineColor: (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
|
||||
padding: (this.options.showScale) ? 0 : this.options.pointRadius + this.options.pointBorderWidth,
|
||||
showLabels: this.options.scaleShowLabels,
|
||||
display: this.options.showScale
|
||||
};
|
||||
|
||||
this.scale.draw(easingDecimal);
|
||||
if (this.options.scaleOverride) {
|
||||
helpers.extend(scaleOptions, {
|
||||
calculateYRange: helpers.noop,
|
||||
steps: this.options.scaleSteps,
|
||||
stepValue: this.options.scaleStepWidth,
|
||||
min: this.options.scaleStartValue,
|
||||
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
|
||||
});
|
||||
}
|
||||
|
||||
this.eachDataset(function(dataset, datasetIndex){
|
||||
this.scale = new Chart.Scale(scaleOptions);
|
||||
},
|
||||
redraw: function() {
|
||||
|
||||
// Transition Point Locations
|
||||
helpers.each(dataset.metaData, function(point, index){
|
||||
point.transition(easingDecimal);
|
||||
},this);
|
||||
},
|
||||
draw: function(ease) {
|
||||
|
||||
// Transition and Draw the line
|
||||
dataset.metaDataset.transition(easingDecimal).draw();
|
||||
var easingDecimal = ease || 1;
|
||||
this.clear();
|
||||
|
||||
// Draw the points
|
||||
helpers.each(dataset.metaData,function(point){
|
||||
point.draw();
|
||||
});
|
||||
},this);
|
||||
this.scale.draw(easingDecimal);
|
||||
|
||||
// Finally draw the tooltip
|
||||
this.tooltip.transition(easingDecimal).draw();
|
||||
}
|
||||
});
|
||||
this.eachDataset(function(dataset, datasetIndex) {
|
||||
|
||||
// Transition Point Locations
|
||||
helpers.each(dataset.metaData, function(point, index) {
|
||||
point.transition(easingDecimal);
|
||||
}, this);
|
||||
|
||||
// Transition and Draw the line
|
||||
dataset.metaDataset.transition(easingDecimal).draw();
|
||||
|
||||
// Draw the points
|
||||
helpers.each(dataset.metaData, function(point) {
|
||||
point.draw();
|
||||
});
|
||||
}, this);
|
||||
|
||||
// Finally draw the tooltip
|
||||
this.tooltip.transition(easingDecimal).draw();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}).call(this);
|
||||
|
||||
Reference in New Issue
Block a user