Merge pull request #1113 from tannerlinsley/deep-data

Deep data
This commit is contained in:
Derek Perkins 2015-05-11 18:53:28 -06:00
commit c7b117631b
3 changed files with 134 additions and 147 deletions

View File

@ -50,6 +50,8 @@
barChartData.datasets[1].data = [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()];
window.myBar.update();
console.log(window.barChartData);
});
</script>

View File

@ -75,8 +75,6 @@
}
});
this.datasets = [];
//Set up tooltip events on the chart
if (this.options.showTooltips){
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
@ -85,6 +83,7 @@
this.eachBars(function(bar){
bar.restore(['fillColor', 'strokeColor']);
});
helpers.each(activeBars, function(activeBar){
activeBar.fillColor = activeBar.highlightFill;
activeBar.strokeColor = activeBar.highlightStroke;
@ -93,107 +92,83 @@
});
}
//Declare the extension of the default point, to cater for the options passed in to the constructor
this.BarClass = Chart.Rectangle.extend({
strokeWidth : this.options.barStrokeWidth,
showStroke : this.options.barShowStroke,
ctx : this.chart.ctx
ctx : this.chart.ctx,
_vm: {}
});
//Iterate through each of the datasets, and build this into a property of the chart
helpers.each(data.datasets,function(dataset,datasetIndex){
var datasetObject = {
label : dataset.label || null,
fillColor : dataset.fillColor,
strokeColor : dataset.strokeColor,
bars : []
};
this.datasets.push(datasetObject);
helpers.each(dataset.data,function(dataPoint,index){
//Add a new point for each piece of data, passing any required data to draw.
datasetObject.bars.push(new this.BarClass({
value : dataPoint,
label : data.labels[index],
datasetLabel: dataset.label,
strokeColor : dataset.strokeColor,
fillColor : dataset.fillColor,
highlightFill : dataset.highlightFill || dataset.fillColor,
highlightStroke : dataset.highlightStroke || dataset.strokeColor
}));
},this);
},this);
// Build Scale
this.buildScale(data.labels);
this.BarClass.prototype.base = this.scale.endPoint;
//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);
// Set defaults for bars
this.eachBars(function(bar, index, datasetIndex){
helpers.extend(bar, {
width : this.scale.calculateBarWidth(this.datasets.length),
x: this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
y: this.scale.endPoint
width : this.scale.calculateBarWidth(this.data.datasets.length),
x: this.scale.calculateBarX(this.data.datasets.length, datasetIndex, index),
y: this.scale.endPoint,
});
// Copy to view model
bar.save();
}, this);
this.render();
this.update();
},
update : function(){
//Iterate through each of the datasets, and build this into a property of the chart
helpers.each(this.data.datasets,function(dataset,datasetIndex){
helpers.extend(this.datasets[datasetIndex], {
label : dataset.label || null,
fillColor : dataset.fillColor,
strokeColor : dataset.strokeColor,
});
helpers.each(dataset.data,function(dataPoint,index){
helpers.extend(this.datasets[datasetIndex].bars[index], {
value : dataPoint,
label : this.data.labels[index],
datasetLabel: dataset.label,
strokeColor : dataset.strokeColor,
fillColor : dataset.fillColor,
highlightFill : dataset.highlightFill || dataset.fillColor,
highlightStroke : dataset.highlightStroke || dataset.strokeColor
});
},this);
},this);
this.scale.update();
// Reset any highlight colours before updating.
helpers.each(this.activeElements, function(activeElement){
activeElement.restore(['fillColor', 'strokeColor']);
});
this.eachBars(function(bar){
bar.save();
});
this.eachBars(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.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,
strokeColor : this.data.datasets[datasetIndex].strokeColor,
fillColor : this.data.datasets[datasetIndex].fillColor,
highlightFill : this.data.datasets[datasetIndex].highlightFill || this.data.datasets[datasetIndex].fillColor,
highlightStroke : this.data.datasets[datasetIndex].highlightStroke || this.data.datasets[datasetIndex].strokeColor,
_start: undefined
});
}, this);
this.render();
},
eachBars : function(callback){
helpers.each(this.datasets,function(dataset, datasetIndex){
helpers.each(dataset.bars, callback, this, datasetIndex);
helpers.each(this.data.datasets,function(dataset, datasetIndex){
helpers.each(dataset.metaData, callback, this, datasetIndex);
},this);
},
eachValue : function(callback){
helpers.each(this.data.datasets,function(dataset, datasetIndex){
helpers.each(dataset.data, callback, this, datasetIndex);
},this);
},
getBarsAtEvent : function(e){
var barsArray = [],
eventPosition = helpers.getRelativePosition(e),
datasetIterator = function(dataset){
barsArray.push(dataset.bars[barIndex]);
barsArray.push(dataset.metaData[barIndex]);
},
barIndex;
for (var datasetIndex = 0; datasetIndex < this.datasets.length; datasetIndex++) {
for (barIndex = 0; barIndex < this.datasets[datasetIndex].bars.length; barIndex++) {
if (this.datasets[datasetIndex].bars[barIndex].inRange(eventPosition.x,eventPosition.y)){
helpers.each(this.datasets, datasetIterator);
for (var datasetIndex = 0; datasetIndex < this.data.datasets.length; datasetIndex++) {
for (barIndex = 0; barIndex < this.data.datasets[datasetIndex].metaData.length; barIndex++) {
if (this.data.datasets[datasetIndex].metaData[barIndex].inRange(eventPosition.x,eventPosition.y)){
helpers.each(this.data.datasets, datasetIterator);
return barsArray;
}
}
@ -206,8 +181,8 @@
var dataTotal = function(){
var values = [];
self.eachBars(function(bar){
values.push(bar.value);
self.eachValue(function(value){
values.push(value);
});
return values;
};
@ -263,16 +238,16 @@
//Map the values array for each of the datasets
helpers.each(valuesArray,function(value,datasetIndex){
//Add a new point for each piece of data, passing any required data to draw.
this.datasets[datasetIndex].bars.push(new this.BarClass({
this.data.datasets[datasetIndex].bars.push(new this.BarClass({
value : value,
label : label,
datasetLabel: this.datasets[datasetIndex].label,
x: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount+1),
datasetLabel: this.data.datasets[datasetIndex].label,
x: this.scale.calculateBarX(this.data.datasets.length, datasetIndex, this.scale.valuesCount+1),
y: this.scale.endPoint,
width : this.scale.calculateBarWidth(this.datasets.length),
width : this.scale.calculateBarWidth(this.data.datasets.length),
base : this.scale.endPoint,
strokeColor : this.datasets[datasetIndex].strokeColor,
fillColor : this.datasets[datasetIndex].fillColor
strokeColor : this.data.datasets[datasetIndex].strokeColor,
fillColor : this.data.datasets[datasetIndex].fillColor
}));
},this);
@ -283,7 +258,7 @@
removeData : function(){
this.scale.removeXLabel();
//Then re-render the chart.
helpers.each(this.datasets,function(dataset){
helpers.each(this.data.datasets,function(dataset){
dataset.bars.shift();
},this);
this.update();
@ -300,28 +275,21 @@
this.scale.update(newScaleProps);
},
draw : function(ease){
var easingDecimal = ease || 1;
this.clear();
var ctx = this.chart.ctx;
this.scale.draw(easingDecimal);
//Draw all the bars for each dataset
helpers.each(this.datasets,function(dataset,datasetIndex){
helpers.each(dataset.bars,function(bar,index){
if (bar.hasValue()){
bar.base = this.scale.endPoint;
//Transition then draw
bar.transition({
x : this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
y : this.scale.calculateY(bar.value),
width : this.scale.calculateBarWidth(this.datasets.length)
}, easingDecimal).draw();
}
},this);
},this);
this.eachBars(function(bar, index, datasetIndex){
if (bar.hasValue()){
// Update the bar basepoint
bar.base = this.scale.endPoint;
//Transition
bar.transition(['x','y','width'], easingDecimal).draw();
}
}, this);
}
});

View File

@ -466,7 +466,6 @@
numberOfSteps = minSteps;
stepValue = graphRange / numberOfSteps;
}
return {
steps : numberOfSteps,
stepValue : stepValue,
@ -1021,12 +1020,12 @@
}
if (ChartElements.length > 0){
// If we have multiple datasets, show a MultiTooltip for all of the data points at that index
if (this.datasets && this.datasets.length > 1) {
if (this.data.datasets && this.data.datasets.length > 1) {
var dataArray,
dataIndex;
for (var i = this.datasets.length - 1; i >= 0; i--) {
dataArray = this.datasets[i].points || this.datasets[i].bars || this.datasets[i].segments;
for (var i = this.data.datasets.length - 1; i >= 0; i--) {
dataArray = this.data.datasets[i].metaData;
dataIndex = indexOf(dataArray, ChartElements[0]);
if (dataIndex !== -1){
break;
@ -1045,8 +1044,8 @@
yMax,
xMin,
yMin;
helpers.each(this.datasets, function(dataset){
dataCollection = dataset.points || dataset.bars || dataset.segments;
helpers.each(this.data.datasets, function(dataset){
dataCollection = dataset.metaData;
if (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue()){
Elements.push(dataCollection[dataIndex]);
}
@ -1060,8 +1059,8 @@
//Include any colour information about the element
tooltipLabels.push(helpers.template(this.options.multiTooltipTemplate, element));
tooltipColors.push({
fill: element._saved.fillColor || element.fillColor,
stroke: element._saved.strokeColor || element.strokeColor
fill: element._vm.fillColor || element.fillColor,
stroke: element._vm.strokeColor || element.strokeColor
});
}, this);
@ -1176,36 +1175,50 @@
Chart.Element = function(configuration){
extend(this,configuration);
this.initialize.apply(this,arguments);
this.save();
};
extend(Chart.Element.prototype,{
initialize : function(){},
restore : function(props){
if (!props){
extend(this,this._saved);
} else {
each(props,function(key){
this[key] = this._saved[key];
},this);
save: function(){
this._vm = clone(this);
delete this._vm._vm;
return this;
},
transition : function(props, ease){
if(!this._start){
this._start = clone(this._vm);
}
return this;
},
save : function(){
this._saved = clone(this);
delete this._saved._saved;
return this;
},
update : function(newProps){
each(newProps,function(value,key){
this._saved[key] = this[key];
this[key] = value;
},this);
return this;
},
transition : function(props,ease){
each(props,function(value,key){
this[key] = ((value - this._saved[key]) * ease) + this._saved[key];
each(this,function(value, key){
// Only non-vm properties
if(key === '_vm' || !this.hasOwnProperty(key)){
return;
}
// Init if doesn't exist
if(!this._vm[key]){
this._vm[key] = value || null;
return;
}
// If transition property, do transition with ease (no pun intended)
if(props.indexOf(key) > -1){
// Color transitions if possible
if(typeof value === 'string'){
// TODO support color transitions
return;
}
// Everything else, presumably numbers
this._vm[key] = ((this[key] - this._start[key]) * ease) + this._start[key];
return;
}
// Non-transitionals
this._vm[key] = value;
},this);
if(ease === 1){
delete this._start;
}
return this;
},
tooltipPosition : function(){
@ -1325,16 +1338,19 @@
Chart.Rectangle = Chart.Element.extend({
draw : function(){
var vm = this._vm;
var ctx = this.ctx,
halfWidth = this.width/2,
leftX = this.x - halfWidth,
rightX = this.x + halfWidth,
top = this.base - (this.base - this.y),
halfStroke = this.strokeWidth / 2;
halfWidth = vm.width/2,
leftX = vm.x - halfWidth,
rightX = vm.x + halfWidth,
top = vm.base - (vm.base - vm.y),
halfStroke = vm.strokeWidth / 2;
// Canvas doesn't allow us to stroke inside the width so we can
// adjust the sizes to fit if we're setting a stroke on the line
if (this.showStroke){
if (vm.showStroke){
leftX += halfStroke;
rightX -= halfStroke;
top += halfStroke;
@ -1342,26 +1358,28 @@
ctx.beginPath();
ctx.fillStyle = this.fillColor;
ctx.strokeStyle = this.strokeColor;
ctx.lineWidth = this.strokeWidth;
ctx.fillStyle = vm.fillColor;
ctx.strokeStyle = vm.strokeColor;
ctx.lineWidth = vm.strokeWidth;
// It'd be nice to keep this class totally generic to any rectangle
// and simply specify which border to miss out.
ctx.moveTo(leftX, this.base);
ctx.moveTo(leftX, vm.base);
ctx.lineTo(leftX, top);
ctx.lineTo(rightX, top);
ctx.lineTo(rightX, this.base);
ctx.lineTo(rightX, vm.base);
ctx.fill();
if (this.showStroke){
if (vm.showStroke){
ctx.stroke();
}
},
height : function(){
return this.base - this.y;
var vm = this._vm;
return vm.base - vm.y;
},
inRange : function(chartX,chartY){
return (chartX >= this.x - this.width/2 && chartX <= this.x + this.width/2) && (chartY >= this.y && chartY <= this.base);
var vm = this._vm;
return (chartX >= vm.x - vm.width/2 && chartX <= vm.x + vm.width/2) && (chartY >= vm.y && chartY <= vm.base);
}
});
@ -2109,8 +2127,7 @@
return animationWrapper.chartInstance === chartInstance;
});
if (index)
{
if (index){
this.animations.splice(index, 1);
}
},