2015-02-14 2 views
2

Я изменяю свои гистограммы с помощью ChartJS, добавляя закругленные прямоугольники, а не прямые, как у них по умолчанию. Я нашел пятно в Chart.js, где объявить закругленный прямоугольник, но Я не называю функцию правильно. Я подумал, что после того, как вы объявите свой «барчер», у вас будет возможность просто добавить точки x, y, width и height. Где вы их добавляете? Любая помощь очень ценится.Как создать округленный прямоугольник с помощью ChartJS

HTML

<!DOCTYPE html> 
<meta charset="utf-8"> 
<head> 
    <title>Bar Chart</title> 
    <script src="Scripts/Chart.js"></script> 
</head> 
<body> 
    <style> 
     body{ 
     background-color:transparent; 
     } 
    </style> 
    <div style="width: 25%"> 
     <canvas id="canvas" height="150" width="225"></canvas> 
    </div> 
    <script> 
     var StandardThroughput = function(){ return Math.round(Math.random()*100)}; 
     var ActualThroughput = function(){ return Math.round(Math.random()*80)}; 

     var barChartData = { 
     labels : ["Standard Throughput","Actual Throughput"], 
     datasets : [ 
      { 
       fillColor : "rgba(0,255,0,0.9)", 
       strokeColor : "#ffffff", 
       //highlightFill: "rgba(220,220,220,0.9)", 
       //highlightStroke: "rgba(220,220,220,1)", 
       data : [StandardThroughput(),ActualThroughput()] 
      } 


     ] 

     } 
     window.onload = function(){ 
     var ctx = document.getElementById("canvas").getContext("2d"); 

     window.myBar = new Chart(ctx).Bar(barChartData,{ 
      responsive : true, 
      scaleShowGridLines : false, 
      scaleShowLabels: false, 
      showTooltips: false, 
      scaleLineWidth: 0.01, 
     }); 
     } 

    </script> 
</body> 

JavaScript

(function(){ 

     drawRoundedRectangle = helpers.drawRoundedRectangle = function(ctx,x,y,width,height,radius){ 
      ctx.beginPath(); 
      ctx.moveTo(x + radius, y); 
      ctx.lineTo(x + width - radius, y); 
      ctx.quadraticCurveTo(x + width, y, x + width, y + radius); 
      ctx.lineTo(x + width, y + height - radius); 
      ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); 
      ctx.lineTo(x + radius, y + height); 
      ctx.quadraticCurveTo(x, y + height, x, y + height - radius); 
      ctx.lineTo(x, y + radius); 
      ctx.quadraticCurveTo(x, y, x + radius, y); 
      ctx.closePath(); 
     }; 

)}; 

ответ

4

С этим я бы расширить базовый класс прямоугольник переопределить метод draw

Chart.RoundedRectangle = Chart.Rectangle.extend({ 
     draw: function() { 
      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, 
       radius = halfWidth; 


      // 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) { 
       leftX += halfStroke; 
       rightX -= halfStroke; 
       top += halfStroke; 
      } 

      ctx.beginPath(); 

      ctx.fillStyle = this.fillColor; 
      ctx.strokeStyle = this.strokeColor; 
      ctx.lineWidth = this.strokeWidth; 


      // stop from creating funky shapes if the radius is bigger than the rectangle we are creating 
      if(radius > (this.base-top)/2) 
      { 
       radius = (this.base-top)/2; 
      } 
      ctx.moveTo(leftX, this.base - radius); 
      ctx.lineTo(leftX, top + radius); 
      ctx.quadraticCurveTo(leftX, top, leftX + radius, top); 
      ctx.lineTo(rightX - radius, top); 
      ctx.quadraticCurveTo(rightX, top, rightX, top + radius); 
      ctx.lineTo(rightX, this.base - radius); 
      ctx.quadraticCurveTo(rightX, this.base, rightX - radius, this.base); 
      ctx.lineTo(leftX + radius, this.base); 
      ctx.quadraticCurveTo(leftX, this.base, leftX, this.base - radius); 



      ctx.fill(); 
      if (this.showStroke) { 
       ctx.stroke(); 
      } 
     }, 

    }); 

, а затем объявить новый тип диаграммы простиралась от Bar, где вы переопределите метод init использовать этот новый класс RoundedRectangle Примечание: вам также необходимо объявить объект helpers, чтобы вы не могли редактировать все ссылки на это в новой диаграмме.

var helpers = Chart.helpers; 
Chart.types.Bar.extend({ 
    name: "MyBar", 
    initialize: function (data) { 

     //Expose options as a scope variable here so we can access it in the ScaleClass 
     var options = this.options; 

     this.ScaleClass = Chart.Scale.extend({ 
      offsetGridLines: true, 
      calculateBarX: function (datasetCount, datasetIndex, barIndex) { 
       //Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar 
       var xWidth = this.calculateBaseWidth(), 
        xAbsolute = this.calculateX(barIndex) - (xWidth/2), 
        barWidth = this.calculateBarWidth(datasetCount); 

       return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth/2; 
      }, 
      calculateBaseWidth: function() { 
       return (this.calculateX(1) - this.calculateX(0)) - (2 * options.barValueSpacing); 
      }, 
      calculateBarWidth: function (datasetCount) { 
       //The padding between datasets is to the right of each bar, providing that there are more than 1 dataset 
       var baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing); 

       return (baseWidth/datasetCount); 
      } 
     }); 

     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); 
      }); 
     } 

     //Declare the extension of the default point, to cater for the options passed in to the constructor 
     this.BarClass = Chart.RoundedRectangle.extend({ 
      strokeWidth: this.options.barStrokeWidth, 
      showStroke: this.options.barShowStroke, 
      ctx: this.chart.ctx 
     }); 

     //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); 

     this.buildScale(data.labels); 

     this.BarClass.prototype.base = this.scale.endPoint; 

     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 
      }); 
      bar.save(); 
     }, this); 

     this.render(); 
    }, 
}); 

вы можете использовать это, как обычно любая диаграмма

пример: http://fiddle.jshell.net/leighking2/fmpu4gyt/

или фрагмент

var helpers = Chart.helpers; 
 
Chart.RoundedRectangle = Chart.Rectangle.extend({ 
 
    draw: function() { 
 
     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, 
 
      radius = halfWidth; 
 

 

 
     // 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) { 
 
      leftX += halfStroke; 
 
      rightX -= halfStroke; 
 
      top += halfStroke; 
 
     } 
 

 
     ctx.beginPath(); 
 

 
     ctx.fillStyle = this.fillColor; 
 
     ctx.strokeStyle = this.strokeColor; 
 
     ctx.lineWidth = this.strokeWidth; 
 

 
     
 
     // stop from creating funky shapes if the radius is bigger than the rectangle we are creating 
 
     if(radius > (this.base-top)/2) 
 
     { 
 
      radius = (this.base-top)/2; 
 
     } 
 
     ctx.moveTo(leftX, this.base - radius); 
 
     ctx.lineTo(leftX, top + radius); 
 
     ctx.quadraticCurveTo(leftX, top, leftX + radius, top); 
 
     ctx.lineTo(rightX - radius, top); 
 
     ctx.quadraticCurveTo(rightX, top, rightX, top + radius); 
 
     ctx.lineTo(rightX, this.base - radius); 
 
     ctx.quadraticCurveTo(rightX, this.base, rightX - radius, this.base); 
 
     ctx.lineTo(leftX + radius, this.base); 
 
     ctx.quadraticCurveTo(leftX, this.base, leftX, this.base - radius); 
 
     
 
     
 
     
 
     ctx.fill(); 
 
     if (this.showStroke) { 
 
      ctx.stroke(); 
 
     } 
 
    }, 
 

 
}); 
 

 
Chart.types.Bar.extend({ 
 
    name: "MyBar", 
 
    initialize: function (data) { 
 

 
     //Expose options as a scope variable here so we can access it in the ScaleClass 
 
     var options = this.options; 
 

 
     this.ScaleClass = Chart.Scale.extend({ 
 
      offsetGridLines: true, 
 
      calculateBarX: function (datasetCount, datasetIndex, barIndex) { 
 
       //Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar 
 
       var xWidth = this.calculateBaseWidth(), 
 
        xAbsolute = this.calculateX(barIndex) - (xWidth/2), 
 
        barWidth = this.calculateBarWidth(datasetCount); 
 

 
       return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth/2; 
 
      }, 
 
      calculateBaseWidth: function() { 
 
       return (this.calculateX(1) - this.calculateX(0)) - (2 * options.barValueSpacing); 
 
      }, 
 
      calculateBarWidth: function (datasetCount) { 
 
       //The padding between datasets is to the right of each bar, providing that there are more than 1 dataset 
 
       var baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing); 
 

 
       return (baseWidth/datasetCount); 
 
      } 
 
     }); 
 

 
     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); 
 
      }); 
 
     } 
 

 
     //Declare the extension of the default point, to cater for the options passed in to the constructor 
 
     this.BarClass = Chart.RoundedRectangle.extend({ 
 
      strokeWidth: this.options.barStrokeWidth, 
 
      showStroke: this.options.barShowStroke, 
 
      ctx: this.chart.ctx 
 
     }); 
 

 
     //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); 
 

 
     this.buildScale(data.labels); 
 

 
     this.BarClass.prototype.base = this.scale.endPoint; 
 

 
     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 
 
      }); 
 
      bar.save(); 
 
     }, this); 
 

 
     this.render(); 
 
    }, 
 
}); 
 

 

 

 
var randomScalingFactor = function() { 
 
    return Math.round(Math.random() * 100) 
 
}; 
 

 
var barChartData = { 
 
    labels: ["January", "February", "March", "April", "May", "June", "July"], 
 
    datasets: [{ 
 
     fillColor: "rgba(220,220,220,0.5)", 
 
     strokeColor: "rgba(220,220,220,0.8)", 
 
     highlightFill: "rgba(220,220,220,0.75)", 
 
     highlightStroke: "rgba(220,220,220,1)", 
 
     data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()] 
 
    }, { 
 
     fillColor: "rgba(151,187,205,0.5)", 
 
     strokeColor: "rgba(151,187,205,0.8)", 
 
     highlightFill: "rgba(151,187,205,0.75)", 
 
     highlightStroke: "rgba(151,187,205,1)", 
 
     data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()] 
 
    }, { 
 
     fillColor: "rgba(15,18,20,0.5)", 
 
     strokeColor: "rgba(15,18,20,0.8)", 
 
     highlightFill: "rgba(15,18,20,0.75)", 
 
     highlightStroke: "rgba(15,18,20,1)", 
 
     data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()] 
 
    }] 
 

 
} 
 
window.onload = function() { 
 
    var ctx = document.getElementById("canvas").getContext("2d"); 
 
    window.myBar = new Chart(ctx).MyBar(barChartData); 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.1/Chart.js"></script> 
 
<div style="width: 50%"> 
 
    <canvas id="canvas" height="450" width="600"></canvas> 
 
</div>

+0

Если кто-то пришел сюда надеетесь делать заочные диаграммы, например меня, проверьте вилку скрипки @ Айвы: http://fiddle.jshell.net/phily245/7m5wkk2g/1/ –

+0

@PhilYoung. Ваш ответ приносит что-то интересное, потому что основание бара плоское. Смешанный с ответом Куинс, как я могу нарисовать только верхний округлый бар? Любые советы – Jibeee

Смежные вопросы