label: 'Dataset 2',
backgroundColor: "rgba(151,187,205,0.5)",
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
+ }, {
+ label: 'Dataset 3',
+ backgroundColor: "rgba(151,187,205,0.5)",
+ data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
+ }, {
+ label: 'Dataset 4',
+ backgroundColor: "rgba(151,187,205,0.5)",
+ data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
+ }, {
+ label: 'Dataset 3',
+ backgroundColor: "rgba(151,187,205,0.5)",
+ data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
}]
- }
+ };
window.onload = function() {
var ctx = document.getElementById("canvas").getContext("2d");
-- window.myBar = new Chart(ctx).Bar(barChartData, {
-- responsive: true,
-- hoverMode: 'label',
-- scaleBeginAtZero: false,
- hoverAnimationDuration: 400
- hoverAnimationDuration: 400,
- stacked: true,
++ window.myBar = new Chart(ctx).Bar({
++ data: barChartData,
++ options: {
++ responsive: true,
++ hoverMode: 'label',
++ scaleBeginAtZero: false,
++ hoverAnimationDuration: 400,
++ stacked: true,
++ }
});
- }
+ };
$('#randomizeData').click(function() {
- barChartData.datasets[0].backgroundColor = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)';
- barChartData.datasets[0].data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
-
- barChartData.datasets[1].backgroundColor = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)';
- barChartData.datasets[1].data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
+ $.each(barChartData.datasets, function(i, dataset) {
+ dataset.backgroundColor = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)';
+ dataset.data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
+ });
window.myBar.update();
});
</script>
window.onload = function(){
var ctx = document.getElementById("chart-area").getContext("2d");
-- window.myDoughnut = new Chart(ctx).Doughnut(doughnutData, {responsive : true});
++ window.myDoughnut = new Chart(ctx).Doughnut({
++ data: doughnutData,
++ options: {
++ responsive : true
++ }
++ });
};
window.onload = function() {
var ctx = document.getElementById("chart-area").getContext("2d");
-- window.myDoughnut = new Chart(ctx).Doughnut(doughnutData, {
-- responsive: true
++ window.myDoughnut = new Chart(ctx).Doughnut({
++ data: doughnutData,
++ options: {
++ responsive: true
++ }
});
};
window.onload = function() {
var ctx1 = document.getElementById("chart1").getContext("2d");
-- window.myLine = new Chart(ctx1).Line(lineChartData, {
-- showScale: false,
-- pointDot : true,
-- responsive: true
++ window.myLine = new Chart(ctx1).Line({
++ data: lineChartData,
++ options: {
++ showScale: false,
++ pointDot : true,
++ responsive: true
++ }
});
var ctx2 = document.getElementById("chart2").getContext("2d");
window.onload = function() {
var ctx = document.getElementById("canvas").getContext("2d");
-- window.myLine = new Chart(ctx).Line(lineChartData, {
-- responsive: true,
- hoverMode: 'label'
- hoverMode: 'label',
- stacked: true
++ window.myLine = new Chart(ctx).Line({
++ data: lineChartData,
++ options: {
++ responsive: true,
++ hoverMode: 'label',
++ stacked: true
++ }
});
};
window.onload = function() {
var ctx1 = document.getElementById("chart-area1").getContext("2d");
-- window.myPie = new Chart(ctx1).Pie(pieData);
++ window.myPie = new Chart(ctx1).Pie({
++ data: pieData
++ });
var ctx2 = document.getElementById("chart-area2").getContext("2d");
-- window.myPie = new Chart(ctx2).Pie(pieData);
++ window.myPie = new Chart(ctx2).Pie({
++ data: pieData
++ });
};
</script>
</body>
window.onload = function(){
var ctx = document.getElementById("chart-area").getContext("2d");
-- window.myPie = new Chart(ctx).Pie(pieData);
++ window.myPie = new Chart(ctx).Pie({
++ data: pieData
++ });
};
$('#randomizeData').click(function(){
window.onload = function(){
var ctx = document.getElementById("chart-area").getContext("2d");
-- window.myPolarArea = new Chart(ctx).PolarArea(polarData, {
-- responsive:true
++ window.myPolarArea = new Chart(ctx).PolarArea({
++ data: polarData,
++ options: {
++ responsive:true
++ }
});
};
};
window.onload = function(){
-- window.myRadar = new Chart(document.getElementById("canvas").getContext("2d")).Radar(radarChartData, {
-- responsive: true
++ window.myRadar = new Chart(document.getElementById("canvas").getContext("2d")).Radar({
++ data: radarChartData,
++ options: {
++ responsive: true
++ }
});
}
--- /dev/null
- window.myScatter = new Chart(ctx).Scatter(scatterChartData, {
- responsive: true,
- hoverMode: 'single',
- scales: {
- xAxes: [{
- position: "bottom",
- gridLines: {
- zeroLineColor: "rgba(0,0,0,1)"
- }
- }],
- yAxes: [{
- scaleType: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
- show: true,
- position: "left",
- horizontal: false,
- id: "y-axis-1",
-
- // grid line settings
- gridLines: {
- show: true,
- color: "rgba(0, 0, 0, 0.05)",
- lineWidth: 1,
- drawOnChartArea: true,
- drawTicks: true,
- zeroLineWidth: 1,
- zeroLineColor: "rgba(0,0,0,0.25)",
- },
+<!doctype html>
+<html>
+
+<head>
+ <title>Scatter Chart Multi Axis</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:50%">
+ <div>
+ <canvas id="canvas" height="450" width="600"></canvas>
+ </div>
+ </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 randomColor = function(opacity) {
+ return 'rgba(' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + (opacity || '.3') + ')';
+ };
+
+ var scatterChartData = {
+ datasets: [{
+ label: "My First dataset",
+ xAxisID: "x-axis-1",
+ yAxisID: "y-axis-1",
+ data: [{
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }]
+ }, {
+ label: "My Second dataset",
+ xAxisID: "x-axis-1",
+ yAxisID: "y-axis-2",
+ data: [{
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }]
+ }]
+ };
+
+ $.each(scatterChartData.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(scatterChartData);
+
+ window.onload = function() {
+ var ctx = document.getElementById("canvas").getContext("2d");
- // scale numbers
- beginAtZero: false,
- integersOnly: false,
- override: null,
++ window.myScatter = new Chart(ctx).Scatter({
++ data: scatterChartData,
++ options: {
++ responsive: true,
++ hoverMode: 'single',
++ scales: {
++ xAxes: [{
++ position: "bottom",
++ gridLines: {
++ zeroLineColor: "rgba(0,0,0,1)"
++ }
++ }],
++ yAxes: [{
++ scaleType: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
++ show: true,
++ position: "left",
++ horizontal: false,
++ id: "y-axis-1",
++
++ // grid line settings
++ gridLines: {
++ show: true,
++ color: "rgba(0, 0, 0, 0.05)",
++ lineWidth: 1,
++ drawOnChartArea: true,
++ drawTicks: true,
++ zeroLineWidth: 1,
++ zeroLineColor: "rgba(0,0,0,0.25)",
++ },
+
- // label settings
- labels: {
- show: true,
- template: "<%=value%>",
- fontSize: 12,
- fontStyle: "normal",
- fontColor: "#666",
- fontFamily: "Helvetica Neue",
- }
- }, {
- scaleType: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
- show: true,
- position: "right",
- horizontal: false,
- id: "y-axis-2",
-
- // grid line settings
- gridLines: {
- show: true,
- color: "rgba(0, 0, 0, 0.05)",
- lineWidth: 1,
- drawOnChartArea: false, // only want the grid lines for one axis to show up
- drawTicks: false,
- zeroLineWidth: 1,
- zeroLineColor: "rgba(0,0,0,0.25)",
- },
++ // scale numbers
++ beginAtZero: false,
++ integersOnly: false,
++ override: null,
+
- // scale numbers
- beginAtZero: false,
- integersOnly: false,
- override: null,
++ // label settings
++ labels: {
++ show: true,
++ template: "<%=value%>",
++ fontSize: 12,
++ fontStyle: "normal",
++ fontColor: "#666",
++ fontFamily: "Helvetica Neue",
++ }
++ }, {
++ scaleType: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
++ show: true,
++ position: "right",
++ horizontal: false,
++ id: "y-axis-2",
++
++ // grid line settings
++ gridLines: {
++ show: true,
++ color: "rgba(0, 0, 0, 0.05)",
++ lineWidth: 1,
++ drawOnChartArea: false, // only want the grid lines for one axis to show up
++ drawTicks: false,
++ zeroLineWidth: 1,
++ zeroLineColor: "rgba(0,0,0,0.25)",
++ },
+
- // label settings
- labels: {
- show: true,
- template: "<%=value%>",
- fontSize: 12,
- fontStyle: "normal",
- fontColor: "#666",
- fontFamily: "Helvetica Neue",
- }
- }],
- }
++ // scale numbers
++ beginAtZero: false,
++ integersOnly: false,
++ override: null,
+
++ // label settings
++ labels: {
++ show: true,
++ template: "<%=value%>",
++ fontSize: 12,
++ fontStyle: "normal",
++ fontColor: "#666",
++ fontFamily: "Helvetica Neue",
++ }
++ }],
++ }
++ }
+ });
+ };
+
+ $('#randomizeData').click(function() {
+ scatterChartData.datasets[0].data = [{
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }];
+ scatterChartData.datasets[1].data = [{
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }]
+ window.myScatter.update();
+ });
+ </script>
+</body>
+
+</html>
--- /dev/null
- window.myScatter = new Chart(ctx).Scatter(scatterChartData, {
- responsive: true,
- hoverMode: 'single', // should always use single for a scatter chart
- scales: {
- xAxes: [{
- gridLines: {
- zeroLineColor: "rgba(0,0,0,1)"
- }
- }]
+<!doctype html>
+<html>
+
+<head>
+ <title>Scatter 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:50%">
+ <div>
+ <canvas id="canvas" height="450" width="600"></canvas>
+ </div>
+ </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 randomColor = function(opacity) {
+ return 'rgba(' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + (opacity || '.3') + ')';
+ };
+
+ var scatterChartData = {
+ datasets: [{
+ label: "My First dataset",
+ data: [{
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }]
+ }, {
+ label: "My Second dataset",
+ data: [{
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }]
+ }]
+ };
+
+ $.each(scatterChartData.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(scatterChartData);
+
+ window.onload = function() {
+ var ctx = document.getElementById("canvas").getContext("2d");
++ window.myScatter = new Chart(ctx).Scatter({
++ data: scatterChartData,
++ options: {
++ responsive: true,
++ hoverMode: 'single', // should always use single for a scatter chart
++ scales: {
++ xAxes: [{
++ gridLines: {
++ zeroLineColor: "rgba(0,0,0,1)"
++ }
++ }]
++ }
+ }
+ });
+ };
+
+ $('#randomizeData').click(function() {
+ scatterChartData.datasets[0].data = [{
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }];
+ scatterChartData.datasets[1].data = [{
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }, {
+ x: randomScalingFactor(),
+ y: randomScalingFactor(),
+ }]
+ window.myScatter.update();
+ });
+ </script>
+</body>
+
+</html>
Chart.Type.extend({
name: "Bar",
defaults: defaultConfig,
-- initialize: function(data) {
--
-- // Save data as a source for updating of values & methods
-- this.data = data;
--
++ initialize: function() {
var options = this.options;
+ var _this = this;
+
// Custom Scale Methods and Options
this.ScaleClass = Chart.Scale.extend({
offsetGridLines: true,
Chart.types[chartName] = ChartType;
//Register this new chart type in the Chart prototype
- Chart.prototype[chartName] = function(data, options) {
- var config = helpers.configMerge(Chart.defaults.global, Chart.defaults[chartName], options || {});
- return new ChartType(data, config, this);
+ Chart.prototype[chartName] = function(config) {
- helpers.extend(config.options, merge(Chart.defaults.global, Chart.defaults[chartName], config.options || {}));
++ config.options = helpers.configMerge(Chart.defaults.global, Chart.defaults[chartName], config.options || {});
+ return new ChartType(config, this);
};
} else {
warn("Name not provided for this chart, so it hasn't been registered");
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;
--
++ initialize: function() {
// Slice Type and defaults
this.Slice = Chart.Arc.extend({
_chart: this.chart,
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;
--
++ initialize: function(){
this.segments = [];
//Declare segment class as a chart instance specific class, so it can share props for this instance
this.SegmentArc = Chart.Arc.extend({
yCenter: this.chart.height/2,
ctx : this.chart.ctx,
templateString: this.options.scaleLabel,
-- valuesCount: data.length
++ valuesCount: this.data.length
});
-- this.updateScaleRange(data);
++ this.updateScaleRange(this.data);
this.scale.update();
-- helpers.each(data,function(segment,index){
++ helpers.each(this.data,function(segment,index){
this.addData(segment,index,true);
},this);
},
-- initialize: function(data){
-- // Save data as a source for updating of values & methods
-- this.data = data;
--
++ initialize: function(){
this.PointClass = Chart.Point.extend({
strokeWidth : this.options.pointDotStrokeWidth,
radius : this.options.pointDotRadius,
this.datasets = [];
-- this.buildScale(data);
++ this.buildScale(this.data);
//Set up tooltip events on the chart
if (this.options.showTooltips){
}
//Iterate through each of the datasets, and build this into a property of the chart
-- helpers.each(data.datasets,function(dataset){
++ helpers.each(this.data.datasets,function(dataset){
var datasetObject = {
label: dataset.label || null,
}
datasetObject.points.push(new this.PointClass({
value : dataPoint,
-- label : data.labels[index],
++ label : this.data.labels[index],
datasetLabel: dataset.label,
x: (this.options.animation) ? this.scale.xCenter : pointPosition.x,
y: (this.options.animation) ? this.scale.yCenter : pointPosition.y,
--- /dev/null
- initialize: function(data) {
- // Save data as a source for updating of values & methods
- this.data = data;
-
+(function() {
+ "use strict";
+
+ var root = this,
+ Chart = root.Chart,
+ helpers = Chart.helpers;
+
+ var defaultConfig = {
+ hoverMode: 'single',
+ scales: {
+ xAxes: [{
+ scaleType: "linear", // scatter should not use a dataset axis
+ show: true,
+ position: "bottom",
+ horizontal: true,
+ id: "x-axis-1", // need an ID so datasets can reference the scale
+
+ // grid line settings
+ gridLines: {
+ show: true,
+ color: "rgba(0, 0, 0, 0.05)",
+ lineWidth: 1,
+ drawOnChartArea: true,
+ drawTicks: true,
+ zeroLineWidth: 1,
+ zeroLineColor: "rgba(0,0,0,0.25)",
+ },
+
+ // scale numbers
+ beginAtZero: false,
+ integersOnly: false,
+ override: null,
+
+ // label settings
+ labels: {
+ show: true,
+ template: "<%=value%>",
+ fontSize: 12,
+ fontStyle: "normal",
+ fontColor: "#666",
+ fontFamily: "Helvetica Neue",
+ },
+ }],
+ yAxes: [{
+ scaleType: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
+ show: true,
+ position: "left",
+ horizontal: false,
+ id: "y-axis-1",
+
+ // grid line settings
+ gridLines: {
+ show: true,
+ color: "rgba(0, 0, 0, 0.05)",
+ lineWidth: 1,
+ drawOnChartArea: true,
+ drawTicks: true, // draw ticks extending towards the label
+ zeroLineWidth: 1,
+ zeroLineColor: "rgba(0,0,0,0.25)",
+ },
+
+ // scale numbers
+ beginAtZero: false,
+ integersOnly: false,
+ override: null,
+
+ // label settings
+ labels: {
+ show: true,
+ template: "<%=value%>",
+ fontSize: 12,
+ fontStyle: "normal",
+ fontColor: "#666",
+ fontFamily: "Helvetica Neue",
+ }
+ }],
+ },
+
+ //Number - Tension of the bezier curve between points
+ tension: 0.4,
+
+ //Number - Radius of each point dot in pixels
+ pointRadius: 4,
+
+ //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 - 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>",
+
+ tooltipTemplate: "(<%= dataX %>, <%= dataY %>)",
+ multiTooltipTemplate: "<%if (datasetLabel){%><%=datasetLabel%>: <%}%>(<%= dataX %>, <%= dataY %>)",
+
+ };
+
+
+ Chart.Type.extend({
+ name: "Scatter",
+ defaults: defaultConfig,
++ initialize: function() {
+ //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);
+
+ // Build Scale
+ this.buildScale();
+ Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
+
+ //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);
+
+ // Make sure each dataset is bound to an x and a y axis
+ if (!dataset.xAxisID) {
+ dataset.xAxisID = this.options.scales.xAxes[0].id;
+ }
+
+ if (!dataset.yAxisID) {
+ dataset.yAxisID = this.options.scales.yAxes[0].id;
+ }
+ }, 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) {
+ var xScale = this.scales[this.data.datasets[datasetIndex].xAxisID];
+
+ helpers.extend(point, {
+ x: xScale.getPixelForValue(index),
+ y: this.chartArea.bottom,
+ _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);
+
+ // 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) {
+ // If exiting chart
+ if (e.type == 'mouseout') {
+ return this;
+ }
+
+ 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);
+
+ // 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
+ }
+ }
+
+ // Built in Tooltips
+ if (this.options.showTooltips) {
+
+ // The usual updates
+ this.tooltip.initialize();
+
+ // 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,
+ });
+ }
+ }
+
+ // 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;
+
+ },
+ update: function() {
+ Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
+
+ // 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.chartArea.top,
+ scaleBottom: this.chartArea.bottom,
+ _points: dataset.metaData,
+ _datasetIndex: datasetIndex,
+ });
+ dataset.metaDataset.pivot();
+ });
+
+ // Update the points
+ this.eachElement(function(point, index, dataset, datasetIndex) {
+ var xScale = this.scales[this.data.datasets[datasetIndex].xAxisID];
+ var yScale = this.scales[this.data.datasets[datasetIndex].yAxisID];
+
+ helpers.extend(point, {
+ x: xScale.getPixelForValue(this.data.datasets[datasetIndex].data[index].x),
+ y: yScale.getPixelForValue(this.data.datasets[datasetIndex].data[index].y),
+ dataX: this.data.datasets[datasetIndex].data[index].x,
+ dataY: this.data.datasets[datasetIndex].data[index].y,
+ label: '', // so that the multitooltip looks ok
+ value: this.data.datasets[datasetIndex].data[index].y, // for legacy reasons
+ 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 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
+ );
+
+ point.controlPointPreviousX = controlPoints.previous.x;
+ point.controlPointNextX = controlPoints.next.x;
+
+ // Prevent the bezier going outside of the bounds of the graph
+
+ // Cap puter bezier handles to the upper/lower scale bounds
+ if (controlPoints.next.y > this.chartArea.bottom) {
+ point.controlPointNextY = this.chartArea.bottom;
+ } else if (controlPoints.next.y < this.chartArea.top) {
+ point.controlPointNextY = this.chartArea.top;
+ } else {
+ point.controlPointNextY = controlPoints.next.y;
+ }
+
+ // Cap inner bezier handles to the upper/lower scale bounds
+ if (controlPoints.previous.y > this.chartArea.bottom) {
+ point.controlPointPreviousY = this.chartArea.bottom;
+ } else if (controlPoints.previous.y < this.chartArea.top) {
+ point.controlPointPreviousY = this.chartArea.top;
+ } else {
+ point.controlPointPreviousY = controlPoints.previous.y;
+ }
+ // Now pivot the point for animation
+ point.pivot();
+ }, this);
+
+ this.render();
+ },
+ buildScale: function() {
+ var self = this;
+
+ var calculateXRange = function() {
+ this.min = null;
+ this.max = null;
+
+ helpers.each(self.data.datasets, function(dataset) {
+ // Only set the scale range for datasets that actually use this axis
+ if (dataset.xAxisID === this.id) {
+ helpers.each(dataset.data, function(value) {
+ if (this.min === null) {
+ this.min = value.x;
+ } else if (value.x < this.min) {
+ this.min = value.x;
+ }
+
+ if (this.max === null) {
+ this.max = value.x;
+ } else if (value.x > this.max) {
+ this.max = value.x;
+ }
+ }, this);
+ }
+ }, this);
+ };
+
+ var calculateYRange = function() {
+ this.min = null;
+ this.max = null;
+
+ helpers.each(self.data.datasets, function(dataset) {
+ if (dataset.yAxisID === this.id) {
+ helpers.each(dataset.data, function(value) {
+ if (this.min === null) {
+ this.min = value.y;
+ } else if (value.y < this.min) {
+ this.min = value.y;
+ }
+
+ if (this.max === null) {
+ this.max = value.y;
+ } else if (value.y > this.max) {
+ this.max = value.y;
+ }
+ }, this);
+ }
+ }, this);
+ };
+
+ // Map of scale ID to scale object so we can lookup later
+ this.scales = {};
+
+ helpers.each(this.options.scales.xAxes, function(xAxisOptions) {
+ var ScaleClass = Chart.scales.getScaleConstructor(xAxisOptions.scaleType);
+ var scale = new ScaleClass({
+ ctx: this.chart.ctx,
+ options: xAxisOptions,
+ calculateRange: calculateXRange,
+ id: xAxisOptions.id,
+ });
+
+ this.scales[scale.id] = scale;
+ }, this);
+
+ helpers.each(this.options.scales.yAxes, function(yAxisOptions) {
+ var ScaleClass = Chart.scales.getScaleConstructor(yAxisOptions.scaleType);
+ var scale = new ScaleClass({
+ ctx: this.chart.ctx,
+ options: yAxisOptions,
+ calculateRange: calculateYRange,
+ id: yAxisOptions.id,
+ });
+
+ this.scales[scale.id] = scale;
+ }, this);
+ },
+ redraw: function() {
+
+ },
+ draw: function(ease) {
+
+ var easingDecimal = ease || 1;
+ this.clear();
+
+ // Draw all the scales
+ helpers.each(this.scales, function(scale) {
+ scale.draw(this.chartArea);
+ }, this);
+
+ 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);