this.eachBars(function(bar){
bar.restore(['fillColor', 'strokeColor']);
});
+
helpers.each(activeBars, function(activeBar){
activeBar.fillColor = activeBar.highlightFill;
activeBar.strokeColor = activeBar.highlightStroke;
});
}
+
+
//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: {}
});
- //Create a new point for each piece of data
+ // Build Scale
+ this.buildScale(data.labels);
+
+ //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){
},this);
},this);
-
+ // Set defaults for bars
this.eachBars(function(bar, index, datasetIndex){
helpers.extend(bar, {
- 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
+ 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.buildScale(data.labels);
- this.BarClass.prototype.base = this.scale.endPoint;
-
this.update();
-
- this.render();
},
update : function(){
- //Create a new point for each piece of data
- helpers.each(this.data.datasets,function(dataset,datasetIndex){
- dataset.metaData = dataset.metaData || [];
- helpers.each(dataset.data,function(dataPoint,index){
- dataset.metaData[index] = dataset.metaData[index] || new this.BarClass();
- },this);
- },this);
+ this.scale.update();
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.endPoint,
+ 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
+ highlightStroke : this.data.datasets[datasetIndex].highlightStroke || this.data.datasets[datasetIndex].strokeColor,
+ _start: undefined
});
- bar.save();
}, this);
- this.scale.update();
this.render();
},
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.data.datasets.length; datasetIndex++) {
- for (barIndex = 0; barIndex < this.data.datasets[datasetIndex].bars.length; barIndex++) {
- if (this.data.datasets[datasetIndex].bars[barIndex].inRange(eventPosition.x,eventPosition.y)){
+ 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;
}
var dataTotal = function(){
var values = [];
- self.eachBars(function(bar){
- values.push(bar.value);
+ self.eachValue(function(value){
+ values.push(value);
});
return values;
};
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
this.eachBars(function(bar, index, datasetIndex){
if (bar.hasValue()){
+ // Update the bar basepoint
bar.base = this.scale.endPoint;
- //Transition then draw
- bar.transition({
- x : this.scale.calculateBarX(this.data.datasets.length, datasetIndex, index),
- y : this.scale.calculateY(bar.value),
- width : this.scale.calculateBarWidth(this.data.datasets.length)
- }, easingDecimal).draw();
- bar.save();
+ //Transition
+ bar.transition(['x','y','width'], easingDecimal).draw();
}
}, this);
}
dataIndex;
for (var i = this.data.datasets.length - 1; i >= 0; i--) {
- dataArray = this.data.datasets[i].points || this.data.datasets[i].bars || this.data.datasets[i].segments;
+ dataArray = this.data.datasets[i].metaData;
dataIndex = indexOf(dataArray, ChartElements[0]);
if (dataIndex !== -1){
break;
xMin,
yMin;
helpers.each(this.data.datasets, function(dataset){
- dataCollection = dataset.points || dataset.bars || dataset.segments;
+ dataCollection = dataset.metaData;
if (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue()){
Elements.push(dataCollection[dataIndex]);
}
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._vm);
- } else {
- each(props,function(key){
- this[key] = this._vm[key];
- },this);
- }
- return this;
- },
- save : function(){
+ save: function(){
this._vm = clone(this);
delete this._vm._vm;
return this;
},
- update : function(newProps){
- each(newProps,function(value,key){
- this._vm[key] = this[key];
- this[key] = value;
- },this);
- return this;
- },
- transition : function(props,ease){
- each(props,function(value,key){
- this._vm[key] = ((value - this._vm[key]) * ease) + this._vm[key];
+ transition : function(props, ease){
+ if(!this._start){
+ this._start = clone(this._vm);
+ }
+ 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(){
halfWidth = vm.width/2,
leftX = vm.x - halfWidth,
rightX = vm.x + halfWidth,
- top = this.base - (this.base - vm.y),
+ top = vm.base - (vm.base - vm.y),
halfStroke = vm.strokeWidth / 2;
// Canvas doesn't allow us to stroke inside the width so we can
// 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 (vm.showStroke){
ctx.stroke();
}
},
height : function(){
- return this.base - vm.y;
+ var vm = this._vm;
+ return vm.base - vm.y;
},
inRange : function(chartX,chartY){
- return (chartX >= vm.x - vm.width/2 && chartX <= vm.x + vm.width/2) && (chartY >= vm.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);
}
});
return animationWrapper.chartInstance === chartInstance;
});
- if (index)
- {
+ if (index){
this.animations.splice(index, 1);
}
},