我正在使用ChartJS修改我的条形图,通过添加圆角矩形而不是像默认情况下的直边。我在Chart.js中找到了声明圆角矩形的位置,但我没有正确调用函数。我想在你宣布你的'条形图'之后,你可以只添加x,y,width和height点。你在哪里添加这些?非常感谢任何帮助。
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();
};
)};
答案 0 :(得分: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>