morrisjs / morris.js

Pretty time-series line graphs
http://morrisjs.github.com/morris.js/
6.92k stars 1.23k forks source link

Morris.Bar broken when single bar width drops below 1px #476

Open axelfontaine opened 10 years ago

axelfontaine commented 10 years ago

It then triggers this exception:

Error: Invalid negative value for <rect> attribute width="-0.17748235887096797" raphael-min.js:10
q raphael-min.js:10
c._engine.rect raphael-min.js:11
v.rect raphael-min.js:10
Morris.Bar.Bar.drawBar morris.js:1619
(anonymous function) morris.js:1536
(anonymous function) morris.js:1543
Morris.Bar.Bar.drawSeries morris.js:1546
Morris.Bar.Bar.draw morris.js:1463
Morris.Grid.Grid.redraw morris.js:472
Morris.Grid.Grid.resizeHandler morris.js:586
__bind morris.js:11

Using Morris 0.5.0 on Chrome 36 32-bit (Win 8.1 x64)

JelteF commented 10 years ago

This means mostly that you have to much data to show in the graph. Some code to handle the exception would be nice, but physically you're unable to display the data in the graph on the screen real estate you have.

nirojsapkota commented 9 years ago

Sorry for the late reply. But i encountered same problem yesterday. The reason for the error is , while drawing the bars in morris.js. it calculates the width of each bar to be drawn by taking the value of Dom element width( where graph is to be drawn) and the size of data. So if the data is large then the width of the bar becomes negative (which morris should have taken care of ) and raphael.js throws exception while trying to set the width of rect to -ve value. For the solution, i added some handling when the width comes negative. Here i calculated the data size that can be fitted within the given dom width by keeping the bar width of 0.5 and removed the additional data. My piece of code is added in the method Bar.prototype.drawSeries = function() {}

/*Fix for negative bar width, trimming the data and calculating the fitting data length and setting bar of size 0.5 */
    if(barWidth <0){
        var fit_data_length = Math.floor(this.width * this.options.barSizeRatio/(numBars*0.5 + this.options.barGap * (numBars-1)));
        //data removed from tail
        this.options.data.splice(fit_data_length);
        barWidth=0.5;}
nicolasbrandt commented 8 years ago

@nirojsapkota I also had to add the following code to prevent barWidth = Infinity :

var barWidth, bottom, groupWidth = 1, idx, lastTop, left, leftPadding, numBars, row, sidx, size, spaceLeft, top, ypos, zeroPos;
      if (this.options.data.length > 0) {
          groupWidth = this.width / this.options.data.length;
      }