From: etimberg Date: Tue, 12 May 2015 12:00:14 +0000 (-0400) Subject: Merge branch 'fix/bar_chart_negative_values' of https://github.com/etimberg/Chart... X-Git-Tag: v2.0-alpha~27^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=460399f6516465cdfe11e867bf017227f0079645;p=thirdparty%2FChart.js.git Merge branch 'fix/bar_chart_negative_values' of https://github.com/etimberg/Chart.js into etimberg-fix/bar_chart_negative_values # Conflicts: # samples/bar.html # src/Chart.Bar.js # src/Chart.Core.js --- 460399f6516465cdfe11e867bf017227f0079645 diff --cc samples/bar.html index 493bd9965,1b1166a22..d1bf880c6 --- a/samples/bar.html +++ b/samples/bar.html @@@ -1,56 -1,46 +1,55 @@@ - - - Bar Chart - - - -
- -
+ + Bar Chart + + + + +
+ +
+ + - + barChartData.datasets[1].backgroundColor = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)'; + barChartData.datasets[1].data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]; + + window.myBar.update(); + + console.log(window.barChartData); + }); + + - diff --cc src/Chart.Bar.js index 1a6ec688f,e911cb500..a65331f30 --- a/src/Chart.Bar.js +++ b/src/Chart.Bar.js @@@ -81,120 -72,103 +81,140 @@@ } }); - this.datasets = []; - //Set up tooltip events on the chart if (this.options.showTooltips){ - helpers.bindEvents(this, this.options.tooltipEvents, function(evt){ - var activeBars = (evt.type !== 'mouseout') ? this.getBarsAtEvent(evt) : []; - - this.eachBars(function(bar){ - bar.restore(['fillColor', 'strokeColor']); - }); - helpers.each(activeBars, function(activeBar){ - activeBar.fillColor = activeBar.highlightFill; - activeBar.strokeColor = activeBar.highlightStroke; - }); - this.showTooltip(activeBars); - }); + 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({ - 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); + // 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){ - //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 - })); + dataset.metaData.push(new this.BarClass()); },this); - },this); - this.buildScale(data.labels); - - this.BarClass.prototype.base = this.calculateBarBase(); - + // 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.calculateBarBase() // so that we animate from the baseline + width : this.scale.calculateBarWidth(this.data.datasets.length), + x: this.scale.calculateBarX(this.data.datasets.length, datasetIndex, index), - y: this.scale.endPoint, ++ y: this.calculateBarBase(), }); + // Copy to view model bar.save(); }, this); - this.render(); + this.update(); + }, + onHover: function(e){ + + var active; + if(e.type == 'mouseout'){ + return false; + } + if(this.options.hoverMode == 'bar'){ + active = this.getBarAtEvent(e); + } + else if(this.options.hoverMode == 'bars'){} + + + // Remove styling for last active + if(this.lastActive){ + if(this.options.hoverMode == 'bar'){ + this.lastActive.rectangle.backgroundColor = this.data.datasets[this.lastActive.datasetIndex].backgroundColor; + this.lastActive.rectangle.borderColor = this.data.datasets[this.lastActive.datasetIndex].borderColor; + this.lastActive.rectangle.borderWidth = 0; + } + else if(this.options.hoverMode == 'bars'){} + } + + // Custom Hover actions + if(this.options.onHover){ + this.options.onHover.call(this, active); + } + else if(active){ + // or default hover action + if(this.options.hoverMode == 'bar'){ + active.rectangle.backgroundColor = this.data.datasets[active.datasetIndex].hoverBackgroundColor || Color(active.rectangle.backgroundColor).saturate(0.5).darken(0.25).rgbString(); + active.rectangle.borderColor = this.data.datasets[active.datasetIndex].hoverBorderColor || Color(active.rectangle.borderColor).saturate(0.5).darken(0.25).rgbString(); + } + else if(this.options.hoverMode == 'bars'){} + + } + + if(!this.animating){ + // If entering + if(!this.lastActive && active){ + this.render(false, this.options.hoverDuration); + } + + // If different bar + if(this.lastActive && active && this.lastActive.rectangle !== active.rectangle){ + this.render(false, this.options.hoverDuration); + } + + // if Leaving + if (this.lastActive && !active){ + this.render(false, this.options.hoverDuration); + } + } + + this.lastActive = active; + + //this.showTooltip(active); }, + // Calculate the base point for the bar. + // If the scale has a 0 point, use that as the base + // If the scale min and max are both positive, use the bottom as a base + // If the scale min and max are both negative, use the top as a base + calculateBarBase: 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.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, + borderColor : this.data.datasets[datasetIndex].borderColor, + borderWidth : this.data.datasets[datasetIndex].borderWidth, + backgroundColor : this.data.datasets[datasetIndex].backgroundColor, + _start: undefined + }); + }, this); + + this.render(); }, eachBars : function(callback){ @@@ -309,16 -257,15 +329,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, - x: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount+1), - y: this.calculateBarBase(), // so that we animate from the 0 point - width : this.scale.calculateBarWidth(this.datasets.length), + datasetLabel: this.data.datasets[datasetIndex].label, + x: this.scale.calculateBarX(this.data.datasets.length, datasetIndex, this.scale.valuesCount+1), - y: this.scale.endPoint, ++ y: this.calculateBarBase(), + width : this.scale.calculateBarWidth(this.data.datasets.length), - base : this.scale.endPoint, + base : this.calculateBarBase(), - strokeColor : this.datasets[datasetIndex].strokeColor, - fillColor : this.datasets[datasetIndex].fillColor + borderColor : this.data.datasets[datasetIndex].borderColor, + backgroundColor : this.data.datasets[datasetIndex].backgroundColor })); },this); @@@ -353,21 -299,23 +373,21 @@@ 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.calculateBarBase() - - //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; ++ bar.base = this.calculateBarBase(); + //Transition + bar.transition([ + 'x', + 'y', + 'width', + 'backgroundColor', + 'borderColor', + 'borderWidth' + ], easingDecimal).draw(); + } + }, this); } }); diff --cc src/Chart.Core.js index 7c051683d,b05b6b971..8a476551b --- a/src/Chart.Core.js +++ b/src/Chart.Core.js @@@ -1380,12 -1276,17 +1380,18 @@@ } }, height : function(){ - return this.base - this.y; + var vm = this._vm; + return vm.base - vm.y; }, inRange : function(chartX,chartY){ - var vm = this._vm; - return (chartX >= vm.x - vm.width/2 && chartX <= vm.x + vm.width/2) && (chartY >= vm.y && chartY <= vm.base); + if (this.y < this.base) + { + return (chartX >= this.x - this.width/2 && chartX <= this.x + this.width/2) && (chartY >= this.y && chartY <= this.base); + } + else + { + return (chartX >= this.x - this.width / 2 && chartX <= this.x + this.width / 2) && (chartY >= this.base && chartY <= this.y); + } } });