return this;
};
+
+ var defaultColor = 'rgba(0,0,0,0.1)';
+
//Globally expose the defaults to allow for user updating/changing
Chart.defaults = {
global: {
-
- // Animation defaults
animation: {
- // Number - Number of animation steps
duration: 1000,
-
- // String - Animation easing effect
easing: "easeOutQuart",
-
- // Function - Will fire on animation progression.
onProgress: function() {},
-
- // Function - Will fire on animation completion.
onComplete: function() {},
},
-
- // Boolean - whether or not the chart should be responsive and resize when the browser does.
responsive: false,
-
- // Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
maintainAspectRatio: true,
-
- // Array - Array of string names to attach interaction events
events: ["mousemove", "mouseout", "click", "touchstart", "touchmove", "touchend"],
-
- // Hover defaults
hover: {
-
- // String || boolean
- mode: 'label', // 'label', 'dataset', 'false'
-
- //Function(event, activeElements) - Custom hover handler
onHover: null,
-
- //Function - Custom hover handler
animationDuration: 400,
},
-
- //Function(event, clickedElements) - Custom click handler
onClick: null,
-
- // Tooltip Defaults
tooltips: {
-
- // Boolean - Determines whether to draw tooltips on the canvas or not - attaches events to touchmove & mousemove
enabled: true,
-
- // Function - Determines whether to draw built-in tooltip or call custom tooltip function
custom: null,
-
- // String - Tooltip background colour
backgroundColor: "rgba(0,0,0,0.8)",
-
- // String - Tooltip label font declaration for the scale label
fontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
-
- // Number - Tooltip label font size in pixels
fontSize: 14,
-
- // String - Tooltip font weight style
fontStyle: "normal",
-
- // String - Tooltip label font colour
fontColor: "#fff",
-
- // String - Tooltip title font declaration for the scale label
titleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
-
- // Number - Tooltip title font size in pixels
titleFontSize: 14,
-
- // String - Tooltip title font weight style
titleFontStyle: "bold",
-
- // String - Tooltip title font colour
titleFontColor: "#fff",
-
- // Number - pixel width of padding around text
yPadding: 6,
-
- // Number - pixel width of padding around text
xPadding: 6,
-
- // Number - Size of the caret on the
caretSize: 8,
-
- // Number - Pixel radius of the border
cornerRadius: 6,
-
- // Number - Pixel offset from point x to edge
xOffset: 10,
-
- // String - Template string for singles
template: "<%if (label){%><%=label%>: <%}%><%= value %>",
-
- // String - Template string for singles
multiTemplate: "<%if (datasetLabel){%><%=datasetLabel%>: <%}%><%= value %>",
-
- // String - Colour behind the legend colour block
multiKeyBackground: '#fff',
},
-
- // Color String - Used for undefined Colros
- defaultColor: 'rgba(0,0,0,0.1)',
-
- }
+ defaultColor: defaultColor,
+
+ // Element defaults
+ elements: {
+ line: {
+ tension: 0.4,
+ backgroundColor: defaultColor,
+ borderWidth: 3,
+ borderColor: defaultColor,
+ // Hover
+ hitRadius: 6,
+ hoverBorderWidth: 2,
+ },
+ point: {
+ radius: 3,
+ backgroundColor: defaultColor,
+ borderWidth: 1,
+ borderColor: defaultColor,
+ // Hover
+ hitRadius: 6,
+ hoverRadius: 5,
+ hoverBorderWidth: 2,
+ },
+ }
+ },
};
//Create a dictionary of chart types, to allow for extension of existing types
return base;
},
+ getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault = function(value, index, defaultValue) {
+ if (!value) {
+ return defaultValue;
+ }
+
+ if (helpers.isArray(value) && index < value.length) {
+ return value[index];
+ }
+
+ return value;
+ },
indexOf = helpers.indexOf = function(arrayToSearch, item) {
if (Array.prototype.indexOf) {
return arrayToSearch.indexOf(item);
};
Chart.Element = function(configuration) {
- extend(this, {
- _vm: {},
- });
extend(this, configuration);
this.initialize.apply(this, arguments);
};
extend(Chart.Element.prototype, {
initialize: function() {},
- save: function() {
- this._vm = clone(this);
- delete this._vm._vm;
- delete this._vm._start;
- return this;
- },
pivot: function() {
- if (this._start) {
- this._start = clone(this);
- helpers.extend(this._start, this._vm);
- }
+ this._start = clone(this._view);
return this;
},
transition: function(ease) {
+ if (!this._view) {
+ this._view = clone(this._model);
+ }
if (!this._start) {
- if (!this._vm) {
- this.save();
- }
- this._start = clone(this._vm);
+ this.pivot();
}
- each(this, function(value, key) {
+ each(this._model, function(value, key) {
if (key[0] === '_' || !this.hasOwnProperty(key)) {
// Only non-underscored properties
}
// Init if doesn't exist
- else if (!this._vm[key]) {
- this._vm[key] = value || null;
+ else if (!this._view[key]) {
+ this._view[key] = value || null;
}
// No unnecessary computations
- else if (this[key] === this._vm[key]) {
+ else if (this[key] === this._view[key]) {
// It's the same! Woohoo!
}
else if (typeof value === 'string') {
try {
var color = helpers.color(this._start[key]).mix(helpers.color(this[key]), ease);
- this._vm[key] = color.rgbString();
+ this._view[key] = color.rgbString();
} catch (err) {
- this._vm[key] = value;
+ this._view[key] = value;
}
}
// Number transitions
else if (typeof value === 'number') {
-
- this._vm[key] = ((this[key] - this._start[key]) * ease) + this._start[key];
- } else {
- // Everything else
- this._vm[key] = value;
+ this._view[key] = ((this[key] - this._start[key]) * ease) + this._start[key];
+ }
+ // Everything else
+ else {
+ this._view[key] = value;
}
}, this);
Chart.Point = Chart.Element.extend({
inRange: function(mouseX, mouseY) {
- var vm = this._vm;
+ var vm = this._view;
var hoverRange = vm.hoverRadius + vm.radius;
return ((Math.pow(mouseX - vm.x, 2) + Math.pow(mouseY - vm.y, 2)) < Math.pow(hoverRange, 2));
},
inGroupRange: function(mouseX) {
- var vm = this._vm;
+ var vm = this._view;
return (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + this.hoverRadius, 2));
},
tooltipPosition: function() {
- var vm = this._vm;
+ var vm = this._view;
return {
x: vm.x,
y: vm.y,
},
draw: function() {
- var vm = this._vm;
+ var vm = this._view;
var ctx = this._chart.ctx;
if (vm.radius > 0 || vm.borderWidth > 0) {
Chart.Line = Chart.Element.extend({
draw: function() {
- var vm = this._vm;
+ var vm = this._view;
var ctx = this._chart.ctx;
- var first = vm._points[0];
- var last = vm._points[vm._points.length - 1];
+ var first = this._children[0];
+ var last = this._children[this._children.length - 1];
// Draw the background first (so the border is always on top)
- helpers.each(vm._points, function(point, index) {
+ helpers.each(this._children, function(point, index) {
if (index === 0) {
- ctx.moveTo(point._vm.x, point._vm.y);
+ ctx.moveTo(point._view.x, point._view.y);
} else {
if (vm._tension > 0 || 1) {
- var previous = this.previousPoint(point, vm._points, index);
+ var previous = this.previousPoint(point, this._children, index);
ctx.bezierCurveTo(
- previous._vm.controlPointNextX,
- previous._vm.controlPointNextY,
- point._vm.controlPointPreviousX,
- point._vm.controlPointPreviousY,
- point._vm.x,
- point._vm.y
+ previous._view.controlPointNextX,
+ previous._view.controlPointNextY,
+ point._view.controlPointPreviousX,
+ point._view.controlPointPreviousY,
+ point._view.x,
+ point._view.y
);
} else {
- ctx.lineTo(point._vm.x, point._vm.y);
+ ctx.lineTo(point._view.x, point._view.y);
}
}
}, this);
if (vm._tension > 0 || 1) {
ctx.bezierCurveTo(
- last._vm.controlPointNextX,
- last._vm.controlPointNextY,
- first._vm.controlPointPreviousX,
- first._vm.controlPointPreviousY,
- first._vm.x,
- first._vm.y
+ last._view.controlPointNextX,
+ last._view.controlPointNextY,
+ first._view.controlPointPreviousX,
+ first._view.controlPointPreviousY,
+ first._view.x,
+ first._view.y
);
} else {
- ctx.lineTo(first._vm.x, first._vm.y);
+ ctx.lineTo(first._view.x, first._view.y);
}
}
- if (vm._points.length > 0) {
+ if (this._children.length > 0) {
//Round off the line by going to the base of the chart, back to the start, then fill.
- ctx.lineTo(vm._points[vm._points.length - 1].x, vm.scaleZero);
- ctx.lineTo(vm._points[0].x, vm.scaleZero);
+ ctx.lineTo(this._children[this._children.length - 1].x, vm.scaleZero);
+ ctx.lineTo(this._children[0].x, vm.scaleZero);
ctx.fillStyle = vm.backgroundColor || Chart.defaults.global.defaultColor;
ctx.closePath();
ctx.fill();
ctx.strokeStyle = vm.borderColor || Chart.defaults.global.defaultColor;
ctx.beginPath();
- helpers.each(vm._points, function(point, index) {
+ helpers.each(this._children, function(point, index) {
if (index === 0) {
- ctx.moveTo(point._vm.x, point._vm.y);
+ ctx.moveTo(point._view.x, point._view.y);
} else {
if (vm._tension > 0 || 1) {
- var previous = this.previousPoint(point, vm._points, index);
+ var previous = this.previousPoint(point, this._children, index);
ctx.bezierCurveTo(
- previous._vm.controlPointNextX,
- previous._vm.controlPointNextY,
- point._vm.controlPointPreviousX,
- point._vm.controlPointPreviousY,
- point._vm.x,
- point._vm.y
+ previous._view.controlPointNextX,
+ previous._view.controlPointNextY,
+ point._view.controlPointPreviousX,
+ point._view.controlPointPreviousY,
+ point._view.x,
+ point._view.y
);
} else {
- ctx.lineTo(point._vm.x, point._vm.y);
+ ctx.lineTo(point._view.x, point._view.y);
}
}
}, this);
if (vm._tension > 0 || 1) {
ctx.bezierCurveTo(
- last._vm.controlPointNextX,
- last._vm.controlPointNextY,
- first._vm.controlPointPreviousX,
- first._vm.controlPointPreviousY,
- first._vm.x,
- first._vm.y
+ last._view.controlPointNextX,
+ last._view.controlPointNextY,
+ first._view.controlPointPreviousX,
+ first._view.controlPointPreviousY,
+ first._view.x,
+ first._view.y
);
} else {
- ctx.lineTo(first._vm.x, first._vm.y);
+ ctx.lineTo(first._view.x, first._view.y);
}
}
Chart.Arc = Chart.Element.extend({
inRange: function(chartX, chartY) {
- var vm = this._vm;
+ var vm = this._view;
var pointRelativePosition = helpers.getAngleFromPoint(vm, {
x: chartX,
//Ensure within the outside of the arc centre, but inside arc outer
},
tooltipPosition: function() {
- var vm = this._vm;
+ var vm = this._view;
var centreAngle = vm.startAngle + ((vm.endAngle - vm.startAngle) / 2),
rangeFromCentre = (vm.outerRadius - vm.innerRadius) / 2 + vm.innerRadius;
draw: function() {
var ctx = this._chart.ctx;
- var vm = this._vm;
+ var vm = this._view;
ctx.beginPath();
Chart.Rectangle = Chart.Element.extend({
draw: function() {
- var vm = this._vm;
+ var vm = this._view;
var ctx = this.ctx,
halfWidth = vm.width / 2,
}
},
height: function() {
- var vm = this._vm;
+ var vm = this._view;
return vm.base - vm.y;
},
inRange: function(mouseX, mouseY) {
- var vm = this._vm;
+ var vm = this._view;
if (vm.y < vm.base) {
return (mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2) && (mouseY >= vm.y && mouseY <= vm.base);
} else {
}
},
inGroupRange: function(mouseX) {
- var vm = this._vm;
+ var vm = this._view;
return (mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2);
},
tooltipPosition: function() {
- var vm = this._vm;
+ var vm = this._view;
if (vm.y < vm.base) {
return {
x: vm.x,
});
helpers.each(elements, function(element) {
- xPositions.push(element._vm.x);
- yPositions.push(element._vm.y);
+ xPositions.push(element._view.x);
+ yPositions.push(element._view.y);
//Include any colour information about the element
labels.push(helpers.template(this._options.tooltips.multiTemplate, element));
colors.push({
- fill: element._vm.backgroundColor,
- stroke: element._vm.borderColor
+ fill: element._view.backgroundColor,
+ stroke: element._view.borderColor
});
}, this);
draw: function() {
var ctx = this._chart.ctx;
- var vm = this._vm;
+ var vm = this._view;
switch (this._options.hover.mode) {
case 'single':
// Custom Tooltips
if (this._custom) {
- this._custom(this._vm);
+ this._custom(this._view);
} else {
switch (vm.yAlign) {
case "above":
}
},
getLineHeight: function(index) {
- var baseLineHeight = this._vm.y - (this._vm.height / 2) + this._vm.yPadding,
+ var baseLineHeight = this._view.y - (this._view.height / 2) + this._view.yPadding,
afterTitleIndex = index - 1;
//If the index is zero, we're getting the title
if (index === 0) {
- return baseLineHeight + this._vm.titleFontSize / 2;
+ return baseLineHeight + this._view.titleFontSize / 2;
} else {
- return baseLineHeight + ((this._vm.fontSize * 1.5 * afterTitleIndex) + this._vm.fontSize / 2) + this._vm.titleFontSize * 1.5;
+ return baseLineHeight + ((this._view.fontSize * 1.5 * afterTitleIndex) + this._view.fontSize / 2) + this._view.titleFontSize * 1.5;
}
},
var defaultConfig = {
+ stacked: false,
+
+ hover: {
+ mode: "label"
+ },
+
+ 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>",
scales: {
xAxes: [{
scaleType: "dataset", // scatter should not use a dataset axis
}
}],
},
-
- //Boolean - Whether to stack the lines essentially creating a stacked area chart.
- stacked: false,
-
- point: {
- // Number - Radius of each point dot in pixels
- radius: 3,
-
- // Number - Pixel width of point dot border
- borderWidth: 1,
-
- // Number - Pixel width of point on hover
- hoverRadius: 5,
-
- // Number - Pixel width of point dot border on hover
- hoverBorderWidth: 2,
-
- // Color
- backgroundColor: Chart.defaults.global.defaultColor,
-
- // Color
- borderColor: Chart.defaults.global.defaultColor,
-
- //Number - amount extra to add to the radius to cater for hit detection outside the drawn point
- hitRadius: 6,
- },
-
- line: {
- //Number - Tension of the bezier curve between points. Use 0 to turn off bezier tension
- tension: 0.4,
- },
-
- //Number - Pixel width of dataset border
- borderWidth: 2,
- //Number - Pixel width of dataset border on hover
- hoverBorderWidth: 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>",
};
defaults: defaultConfig,
initialize: function() {
+ var _this = this;
+
// Events
helpers.bindEvents(this, this.options.events, this.events);
- var _this = this;
-
- //Create a new line and its points for each dataset and piece of data
+ // 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.metaDataset = new Chart.Line({
+ _chart: this.chart,
+ _datasetIndex: datasetIndex,
+ _points: dataset.metaData,
+ });
+
dataset.metaData = [];
+
helpers.each(dataset.data, function(dataPoint, index) {
- dataset.metaData.push(new Chart.Point());
+ dataset.metaData.push(new Chart.Point({
+ _datasetIndex: datasetIndex,
+ _index: index,
+ _chart: this.chart,
+ _model: {
+ x: 0,//xScale.getPixelForValue(null, index, true),
+ y: 0, //this.chartArea.bottom,
+ controlPointPreviousX: this.previousPoint(dataset.data, index).x,
+ controlPointPreviousY: this.nextPoint(dataset.data, index).y,
+ controlPointNextX: this.previousPoint(dataset.data, index).x,
+ controlPointNextY: this.nextPoint(dataset.data, index).y,
+ },
+ }));
}, this);
- // The line chart only supports a single x axis because the x axis is always a dataset axis
+ // The line chart onlty supports a single x axis because the x axis is always a dataset axis
dataset.xAxisID = this.options.scales.xAxes[0].id;
if (!dataset.yAxisID) {
dataset.yAxisID = this.options.scales.yAxes[0].id;
}
+
}, this);
// Build and fit the scale. Needs to happen after the axis IDs have been set
this.buildScale();
- Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
-
- // Set defaults for lines
- this.eachDataset(function(dataset, datasetIndex) {
- helpers.extend(dataset.metaDataset, {
- _points: dataset.metaData,
- _datasetIndex: datasetIndex,
- _chart: this.chart,
- });
- // Fill in dataset defaults from options
- helpers.extend(dataset, helpers.merge(this.options, dataset));
- // Copy to view modele
- 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(null, index, true),
- 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({
_options: this.options,
}, this);
+ // Update that shiz
this.update();
},
nextPoint: function(collection, index) {
return collection[index + 1] || collection[index];
},
update: function() {
+
Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
// Update the lines
helpers.extend(dataset.metaDataset, {
// Utility
+ _scale: yScale,
_datasetIndex: datasetIndex,
-
// Data
- _points: dataset.metaData,
-
- // Geometry
- scaleTop: yScale.top,
- scaleBottom: yScale.bottom,
- scaleZero: yScale.getPixelForValue(0),
-
- // Appearance
- tension: dataset.tension || this.options.line.tension,
- backgroundColor: dataset.backgroundColor || this.options.backgroundColor,
- borderWidth: dataset.borderWidth || this.options.borderWidth,
- borderColor: dataset.borderColor || this.options.borderColor,
+ _children: dataset.metaData,
+ // Model
+ _model: {
+ // Appearance
+ tension: dataset.tension || this.options.elements.line.tension,
+ backgroundColor: dataset.backgroundColor || this.options.elements.line.backgroundColor,
+ borderWidth: dataset.borderWidth || this.options.elements.line.borderWidth,
+ borderColor: dataset.borderColor || this.options.elements.line.borderColor,
+ // Scale
+ scaleTop: yScale.top,
+ scaleBottom: yScale.bottom,
+ scaleZero: yScale.getPixelForValue(0),
+ },
});
+
dataset.metaDataset.pivot();
});
helpers.extend(point, {
// Utility
_chart: this.chart,
+ _xScale: xScale,
+ _yScale: yScale,
_datasetIndex: datasetIndex,
_index: index,
- // Data
- label: this.data.labels[index],
- value: this.data.datasets[datasetIndex].data[index],
- datasetLabel: this.data.datasets[datasetIndex].label,
-
- // Geometry
- offsetGridLines: this.options.offsetGridLines,
- x: xScale.getPixelForValue(null, index, true), // value not used in dataset scale, but we want a consistent API between scales
- y: yScale.getPointPixelForValue(this.data.datasets[datasetIndex].data[index], index, datasetIndex),
- tension: this.data.datasets[datasetIndex].metaDataset.tension,
-
- // Appearnce
- radius: this.data.datasets[datasetIndex].pointRadius || this.options.point.radius,
- backgroundColor: this.data.datasets[datasetIndex].pointBackgroundColor || this.options.point.backgroundColor,
- borderWidth: this.data.datasets[datasetIndex].pointBorderWidth || this.options.point.borderWidth,
-
- // Tooltip
- hoverRadius: this.data.datasets[datasetIndex].pointHitRadius || this.options.point.hitRadius,
+ // Desired view properties
+ _model: {
+ x: xScale.getPixelForValue(null, index, true), // value not used in dataset scale, but we want a consistent API between scales
+ y: yScale.getPointPixelForValue(this.data.datasets[datasetIndex].data[index], index, datasetIndex),
+
+ // Appearance
+ tension: point.custom && point.custom.tension ? point.custom.tension : this.options.elements.line.tension,
+ radius: point.custom && point.custom.radius ? point.custom.pointRadius : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointRadius, index, this.options.elements.point.radius),
+ backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBackgroundColor, index, this.options.elements.point.backgroundColor),
+ borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBorderColor, index, this.options.elements.point.borderColor),
+ borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBorderWidth, index, this.options.elements.point.borderWidth),
+
+ // Tooltip
+ hoverRadius: point.custom && point.custom.hoverRadius ? point.custom.hoverRadius : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointHitRadius, index, this.options.elements.point.hitRadius),
+ },
});
}, 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
+ this.previousPoint(dataset, index)._model,
+ point._model,
+ this.nextPoint(dataset, index)._model,
+ point._model.tension
);
- point.controlPointPreviousX = controlPoints.previous.x;
- point.controlPointNextX = controlPoints.next.x;
+ point._model.controlPointPreviousX = controlPoints.previous.x;
+ point._model.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;
+ point._model.controlPointNextY = this.chartArea.bottom;
} else if (controlPoints.next.y < this.chartArea.top) {
- point.controlPointNextY = this.chartArea.top;
+ point._model.controlPointNextY = this.chartArea.top;
} else {
- point.controlPointNextY = controlPoints.next.y;
+ point._model.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;
+ point._model.controlPointPreviousY = this.chartArea.bottom;
} else if (controlPoints.previous.y < this.chartArea.top) {
- point.controlPointPreviousY = this.chartArea.top;
+ point._model.controlPointPreviousY = this.chartArea.top;
} else {
- point.controlPointPreviousY = controlPoints.previous.y;
+ point._model.controlPointPreviousY = controlPoints.previous.y;
}
+
// Now pivot the point for animation
point.pivot();
}, this);
this.scales[scale.id] = scale;
}, this);
- },
- redraw: function() {
-
},
draw: function(ease) {
}
var dataset;
+ var index;
// Remove styling for last active (even if it may still be active)
if (this.lastActive.length) {
switch (this.options.hover.mode) {
case 'single':
dataset = this.data.datasets[this.lastActive[0]._datasetIndex];
+ index = this.lastActive[0]._index;
- this.lastActive[0].radius = dataset.pointRadius;
- this.lastActive[0].backgroundColor = dataset.pointBackgroundColor;
- this.lastActive[0].borderColor = dataset.pointBorderColor;
- this.lastActive[0].borderWidth = dataset.pointBorderWidth;
+ this.lastActive[0]._model.radius = this.lastActive[0].custom && this.lastActive[0].custom.radius ? this.lastActive[0].custom.pointRadius : helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, this.options.elements.point.radius);
+ this.lastActive[0]._model.backgroundColor = this.lastActive[0].custom && this.lastActive[0].custom.backgroundColor ? this.lastActive[0].custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, this.options.elements.point.backgroundColor);
+ this.lastActive[0]._model.borderColor = this.lastActive[0].custom && this.lastActive[0].custom.borderColor ? this.lastActive[0].custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, this.options.elements.point.borderColor);
+ this.lastActive[0]._model.borderWidth = this.lastActive[0].custom && this.lastActive[0].custom.borderWidth ? this.lastActive[0].custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.options.elements.point.borderWidth);
break;
case 'label':
for (var i = 0; i < this.lastActive.length; i++) {
dataset = this.data.datasets[this.lastActive[i]._datasetIndex];
+ index = this.lastActive[i]._index;
- this.lastActive[i].radius = dataset.pointRadius;
- this.lastActive[i].backgroundColor = dataset.pointBackgroundColor;
- this.lastActive[i].borderColor = dataset.pointBorderColor;
- this.lastActive[i].borderWidth = dataset.pointBorderWidth;
+ this.lastActive[i]._model.radius = this.lastActive[i].custom && this.lastActive[i].custom.radius ? this.lastActive[i].custom.pointRadius : helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, this.options.elements.point.radius);
+ this.lastActive[i]._model.backgroundColor = this.lastActive[i].custom && this.lastActive[i].custom.backgroundColor ? this.lastActive[i].custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, this.options.elements.point.backgroundColor);
+ this.lastActive[i]._model.borderColor = this.lastActive[i].custom && this.lastActive[i].custom.borderColor ? this.lastActive[i].custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, this.options.elements.point.borderColor);
+ this.lastActive[i]._model.borderWidth = this.lastActive[i].custom && this.lastActive[i].custom.borderWidth ? this.lastActive[i].custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.options.elements.point.borderWidth);
}
break;
case 'dataset':
switch (this.options.hover.mode) {
case 'single':
dataset = this.data.datasets[this.active[0]._datasetIndex];
+ index = this.active[0]._index;
- this.active[0].radius = dataset.pointHoverRadius || dataset.pointRadius + 2;
- this.active[0].backgroundColor = dataset.pointHoverBackgroundColor || helpers.color(dataset.pointBackgroundColor).saturate(0.5).darken(0.35).rgbString();
- this.active[0].borderColor = dataset.pointHoverBorderColor || helpers.color(dataset.pointBorderColor).saturate(0.5).darken(0.35).rgbString();
- this.active[0].borderWidth = dataset.pointHoverBorderWidth || dataset.pointBorderWidth + 2;
+ this.active[0]._model.radius = this.active[0].custom && this.active[0].custom.hoverRadius ? this.active[0].custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.active[0]._model.radius + 2);
+ this.active[0]._model.backgroundColor = this.active[0].custom && this.active[0].custom.hoverBackgroundColor ? this.active[0].custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(this.active[0]._model.backgroundColor).saturate(0.5).darken(0.35).rgbString());
+ this.active[0]._model.borderColor = this.active[0].custom && this.active[0].custom.hoverBorderColor ? this.active[0].custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(this.active[0]._model.borderColor).saturate(0.5).darken(0.35).rgbString());
+ this.active[0]._model.borderWidth = this.active[0].custom && this.active[0].custom.hoverBorderWidth ? this.active[0].custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.active[0]._model.borderWidth + 2);
break;
case 'label':
for (var i = 0; i < this.active.length; i++) {
dataset = this.data.datasets[this.active[i]._datasetIndex];
+ index = this.active[i]._index;
- this.active[i].radius = dataset.pointHoverRadius || dataset.pointRadius + 2;
- this.active[i].backgroundColor = dataset.pointHoverBackgroundColor || helpers.color(dataset.pointBackgroundColor).saturate(0.5).darken(0.35).rgbString();
- this.active[i].borderColor = dataset.pointHoverBorderColor || helpers.color(dataset.pointBorderColor).saturate(0.5).darken(0.35).rgbString();
- this.active[i].borderWidth = dataset.pointHoverBorderWidth || dataset.pointBorderWidth + 2;
+ this.active[i]._model.radius = this.active[i].custom && this.active[i].custom.hoverRadius ? this.active[i].custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.active[i]._model.radius + 2);
+ this.active[i]._model.backgroundColor = this.active[i].custom && this.active[i].custom.hoverBackgroundColor ? this.active[i].custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(this.active[i]._model.backgroundColor).saturate(0.5).darken(0.35).rgbString());
+ this.active[i]._model.borderColor = this.active[i].custom && this.active[i].custom.hoverBorderColor ? this.active[i].custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(this.active[i]._model.borderColor).saturate(0.5).darken(0.35).rgbString());
+ this.active[i]._model.borderWidth = this.active[i].custom && this.active[i].custom.hoverBorderWidth ? this.active[i].custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.active[i]._model.borderWidth + 2);
}
break;
case 'dataset':