How to create rounded bars for Bar Chart.js v2?(如何为 Bar Chart.js v2 创建圆角条?)
问题描述
尝试圆条上的条在这篇文章中找到的图表 与提供的 jsFiddle 中显示的一样.这是针对第 1 版的.
在我使用的图表中,它无法加载对 Chart.types.Bar.extend
中的 extend
的引用使脚本崩溃.
如果我使用默认选项,图表加载没有问题.我必须将 Chart.types.Bar.extend
放在末尾,才能正确加载默认选项.运行并全屏查看.
我尝试使用我的 Chart.js 2.4.0 版本来实现这一点.
Chrome 报告:
<块引用>未捕获的类型错误:无法读取未定义的属性扩展"图表.js
这段代码甚至不会在这里运行.为什么会出现这种情况?有人可以帮助我吗?
此代码适用于旧版本的 Chart.js 1.0.谁能进一步展示这如何与 Chart.js 2.0 版本一起使用?谢谢.
$(document).ready(function(){var myBarChart1 = new Chart($('#appBarChart2_NoRound'), {类型:'酒吧',数据:dataBar2,选项:选项栏});var ctx = $("#appBarChart2").getContext("2d");var myBarChart2 = new Chart(ctx).BarAlt(dataBarAlt2, {//0(平坦)到 1(更弯曲)曲率:1});});var dataBarAlt2 = {标签:[一月",二月",三月",四月",五月",六月",七月"],数据集:[{填充颜色:#1A9BFC",strokeColor: "#1A9BFC",数据:[65、59、80、81、56、55、40],}]};var dataBar2 = {标签:[一月",二月",三月",四月",五月",六月",七月"],数据集:[{标签:我的第一个数据集",背景颜色:'#1A9BFC',边框颜色:'#1A9BFC',边框宽度:1,数据:[65、59、80、81、56、55、40],}]};var optionsBar ={秤:{x轴:[{堆叠:真实,酒吧厚度:20,网格线:{显示:假,}//barPercentage:0.5,}],y轴:[{堆叠:真实,//barPercentage:0.5,}]},传奇: {显示:假,//位置:'左'}};Chart.types.Bar.extend({名称:BarAlt",初始化:函数(数据){Chart.types.Bar.prototype.initialize.apply(this, arguments);if (this.options.curvature !== undefined && this.options.curvature <= 1) {var rectangleDraw = this.datasets[0].bars[0].draw;变种自我=这个;var radius = this.datasets[0].bars[0].width * this.options.curvature * 0.5;//用我们的覆盖矩形绘制this.datasets.forEach(函数(数据集){dataset.bars.forEach(function (bar) {bar.draw = 函数 () {//将原始条向下绘制一点(以便我们的曲线将其带到其原始位置)var y = bar.y;//最小值是必需的,因此动画不会从轴下方开始bar.y = Math.min(bar.y + radius, self.scale.endPoint - 1);//根据我们可以绘制多少曲线来调整条形半径var barRadius = (bar.y - y);rectangleDraw.apply(bar, arguments);//在顶部画一个圆角矩形Chart.helpers.drawRoundedRectangle(self.chart.ctx, bar.x - bar.width/2, bar.y - barRadius + 1, bar.width, bar.height, barRadius);ctx.fill();//恢复y值bar.y = y;}})})}}});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.js"></脚本><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><p>条形图 - 工作</p><画布id="appBarChart2_NoRound" height="100" ></div><p>圆形条形图 - 不工作</p><canvas id="appBarChart2" height="100" ></div> 解决方案 您尝试使用的代码实际上适用于 chart.js v1,并且正如您所发现的,它不适用于 chart.js v2(这几乎一个完整的chart.js重写).
要在 chart.js v2 中获得相同的结果,您需要扩展 Chart.elements.Rectangle
并覆盖它的 draw
方法以绘制圆顶.已经有一个chart.js 辅助方法会绘制一个圆角矩形(Chart.helpers.drawRoundedRectangle
),所以我们将稍微修改它并创建一个新的辅助方法,它只会绘制一个圆角顶部(而不是所有方面).
//绘制一个圆角矩形Chart.helpers.drawRoundedTopRectangle = function(ctx, x, y, width, height, radius) {ctx.beginPath();ctx.moveTo(x + 半径, y);//右上角ctx.lineTo(x + 宽度 - 半径, y);ctx.quadraticCurveTo(x + width, y, x + width, y + radius);//右下角ctx.lineTo(x + 宽度, y + 高度);//左下角ctx.lineTo(x, y + 高度);//左上方ctx.lineTo(x, y + 半径);ctx.quadraticCurveTo(x, y, x + radius, y);ctx.closePath();};Chart.elements.RoundedTopRectangle = Chart.elements.Rectangle.extend({画:函数(){var ctx = this._chart.ctx;var vm = this._view;var 左、右、上、下、signX、signY、borderSkipped;varborderWidth = vm.borderWidth;如果(!vm.horizontal){//酒吧左 = vm.x - vm.width/2;右 = vm.x + vm.width/2;顶部 = vm.y;底部 = vm.base;符号X = 1;符号Y = 底部>最佳?1:-1;borderSkipped = vm.borderSkipped ||'底部';} 别的 {//水平条左 = vm.base;对 = vm.x;顶部 = vm.y - vm.height/2;底部 = vm.y + vm.height/2;符号X = 右 >剩下?1:-1;符号Y = 1;borderSkipped = vm.borderSkipped ||'剩下';}//画布不允许我们在宽度内描边,所以我们可以//如果我们要在线上设置笔划,请调整大小以适应如果(边框宽度){//borderWidth 应该小于条宽和条高.var barSize = Math.min(Math.abs(左 - 右), Math.abs(上 - 下));边框宽度 = 边框宽度 >条码?barSize:边框宽度;var halfStroke = 边框宽度/2;//当 bar 顶部位置接近 vm.base(zero) 时调整borderWidth.var borderLeft = left + (borderSkipped !== 'left'?halfStroke * signX: 0);var borderRight = right + (borderSkipped !== 'right'?-halfStroke * signX: 0);var borderTop = top + (borderSkipped !== 'top'?halfStroke * signY: 0);var borderBottom = bottom + (borderSkipped !== 'bottom'?-halfStroke * signY: 0);//不会变成垂直线?if (borderLeft !== borderRight) {顶部 = 边界顶部;底部 = 边界底部;}//不会变成水平线?如果(边界顶部!== 边界底部){左=边界左;右=边界右;}}//计算条形宽度和圆度var barWidth = Math.abs(左 - 右);var roundness = this._chart.config.options.barRoundness ||0.5;var 半径 = barWidth * 圆度 * 0.5;//跟踪栏的原始顶部var prevTop = 顶部;//将顶部向下移动,以便有空间绘制圆角顶部顶部 = 上一页顶部 + 半径;var barRadius = top - prevTop;ctx.beginPath();ctx.fillStyle = vm.backgroundColor;ctx.strokeStyle = vm.borderColor;ctx.lineWidth = 边框宽度;//绘制圆角顶部矩形Chart.helpers.drawRoundedTopRectangle(ctx, left, (top - barRadius + 1), barWidth, bottom - prevTop, barRadius);ctx.fill();如果(边框宽度){ctx.stroke();}//恢复原始的顶部值,所以工具提示和比例仍然有效顶部 = 上一页顶部;},});
接下来,您还必须扩展条形图控制器 (Chart.controllers.bar
) 并覆盖 dataElementType
以使用新的圆角矩形"作为图表而不是常规的矩形.
Chart.defaults.roundedBar = Chart.helpers.clone(Chart.defaults.bar);Chart.controllers.roundedBar = Chart.controllers.bar.extend({dataElementType:Chart.elements.RoundedTopRectangle});
最后,我们将修改图表的配置以使用上面创建的新图表类型,并添加一个名为 barRoundness
的新选项属性来控制顶部的圆度(0 是平的,1 是半-圆圈).
var ctx = document.getElementById("canvas").getContext("2d");var myBar = new Chart(ctx, {类型:'roundedBar',数据: {标签:[汽车",自行车",步行"],数据集:[{标签:'学生',背景颜色:chartColors.blue,数据: [随机缩放因子(),随机缩放因子(),随机缩放因子(),]}, {标签:'老师',背景颜色:chartColors.red,数据: [随机缩放因子(),随机缩放因子(),随机缩放因子(),]}, {标签:'访客',背景颜色:chartColors.green,数据: [随机缩放因子(),随机缩放因子(),随机缩放因子(),]}]},选项: {响应式:真实,条圆度:1,标题: {显示:真,文本:Chart.js - 圆顶条形图(drawRoundedTopRectangle 方法)"},}});
您可以在此 codepen 中查看完整的工作示例.
此外,如果您想要稍微不同的圆顶"外观,这里还有另一个 codepen 使用不同的方法来绘制顶部(一条二次曲线).
Trying to round the bars on bar chart as found in this post that works as displayed in the jsFiddle provided. This is for version 1.
In the chart that I am using, it fails to load for the reference to extend
in Chart.types.Bar.extend
crashes the script.
If I use the default option, the chart loads no problems. I had to place the Chart.types.Bar.extend
at the end for the default option to load correctly. Run and View this in Full Screen.
I tried implementing this with my version of Chart.js 2.4.0.
Chrome reports:
Uncaught TypeError: Cannot read property 'extend' of undefined
chart.js
This code will not even run here. Why is this occurring? Could someone please assist me.
This code works with an older version of Chart.js 1.0. Could anyone please further display how this could work with version Chart.js 2.0? Thank you.
$(document).ready(function(){
var myBarChart1 = new Chart($('#appBarChart2_NoRound'), {
type: 'bar',
data: dataBar2,
options: optionsBar
});
var ctx = $("#appBarChart2").getContext("2d");
var myBarChart2 = new Chart(ctx).BarAlt(dataBarAlt2, {
// 0 (flat) to 1 (more curvy)
curvature: 1
});
});
var dataBarAlt2 = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
fillColor: "#1A9BFC",
strokeColor: "#1A9BFC",
data: [65, 59, 80, 81, 56, 55, 40],
}
]
};
var dataBar2 = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
backgroundColor: '#1A9BFC',
borderColor:'#1A9BFC',
borderWidth: 1,
data: [65, 59, 80, 81, 56, 55, 40],
}
]
};
var optionsBar =
{
scales: {
xAxes: [{
stacked: true,
barThickness: 20,
gridLines:{
display:false,
}
// barPercentage:0.5,
}],
yAxes: [{
stacked: true,
// barPercentage:0.5,
}]
},
legend: {
display: false,
// position: 'left'
}
};
Chart.types.Bar.extend({
name: "BarAlt",
initialize: function (data) {
Chart.types.Bar.prototype.initialize.apply(this, arguments);
if (this.options.curvature !== undefined && this.options.curvature <= 1) {
var rectangleDraw = this.datasets[0].bars[0].draw;
var self = this;
var radius = this.datasets[0].bars[0].width * this.options.curvature * 0.5;
// override the rectangle draw with ours
this.datasets.forEach(function (dataset) {
dataset.bars.forEach(function (bar) {
bar.draw = function () {
// draw the original bar a little down (so that our curve brings it to its original position)
var y = bar.y;
// the min is required so animation does not start from below the axes
bar.y = Math.min(bar.y + radius, self.scale.endPoint - 1);
// adjust the bar radius depending on how much of a curve we can draw
var barRadius = (bar.y - y);
rectangleDraw.apply(bar, arguments);
// draw a rounded rectangle on top
Chart.helpers.drawRoundedRectangle(self.chart.ctx, bar.x - bar.width / 2, bar.y - barRadius + 1, bar.width, bar.height, barRadius);
ctx.fill();
// restore the y value
bar.y = y;
}
})
})
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<p>Bar Chart - Working</p>
<canvas id="appBarChart2_NoRound" height="100" >
</div>
<div>
<p>Rounded Bar Chart - Not Working</p>
<canvas id="appBarChart2" height="100" >
</div>
解决方案 The code that you were trying to use is actually for chart.js v1 and, as you discovered, does not work for chart.js v2 (which is almost a full chart.js re-write).
To achieve the same results in chart.js v2, you need to extend Chart.elements.Rectangle
and overwrite it's draw
method in order to paint the rounded top. There is already a chart.js helper method that will draw a rounded rectangle (Chart.helpers.drawRoundedRectangle
), so we will modify it slightly and create a new helper method that will only draw a rounded top (instead of all sides).
// draws a rectangle with a rounded top
Chart.helpers.drawRoundedTopRectangle = function(ctx, x, y, width, height, radius) {
ctx.beginPath();
ctx.moveTo(x + radius, y);
// top right corner
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
// bottom right corner
ctx.lineTo(x + width, y + height);
// bottom left corner
ctx.lineTo(x, y + height);
// top left
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
};
Chart.elements.RoundedTopRectangle = Chart.elements.Rectangle.extend({
draw: function() {
var ctx = this._chart.ctx;
var vm = this._view;
var left, right, top, bottom, signX, signY, borderSkipped;
var borderWidth = vm.borderWidth;
if (!vm.horizontal) {
// bar
left = vm.x - vm.width / 2;
right = vm.x + vm.width / 2;
top = vm.y;
bottom = vm.base;
signX = 1;
signY = bottom > top? 1: -1;
borderSkipped = vm.borderSkipped || 'bottom';
} else {
// horizontal bar
left = vm.base;
right = vm.x;
top = vm.y - vm.height / 2;
bottom = vm.y + vm.height / 2;
signX = right > left? 1: -1;
signY = 1;
borderSkipped = vm.borderSkipped || 'left';
}
// 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 (borderWidth) {
// borderWidth shold be less than bar width and bar height.
var barSize = Math.min(Math.abs(left - right), Math.abs(top - bottom));
borderWidth = borderWidth > barSize? barSize: borderWidth;
var halfStroke = borderWidth / 2;
// Adjust borderWidth when bar top position is near vm.base(zero).
var borderLeft = left + (borderSkipped !== 'left'? halfStroke * signX: 0);
var borderRight = right + (borderSkipped !== 'right'? -halfStroke * signX: 0);
var borderTop = top + (borderSkipped !== 'top'? halfStroke * signY: 0);
var borderBottom = bottom + (borderSkipped !== 'bottom'? -halfStroke * signY: 0);
// not become a vertical line?
if (borderLeft !== borderRight) {
top = borderTop;
bottom = borderBottom;
}
// not become a horizontal line?
if (borderTop !== borderBottom) {
left = borderLeft;
right = borderRight;
}
}
// calculate the bar width and roundess
var barWidth = Math.abs(left - right);
var roundness = this._chart.config.options.barRoundness || 0.5;
var radius = barWidth * roundness * 0.5;
// keep track of the original top of the bar
var prevTop = top;
// move the top down so there is room to draw the rounded top
top = prevTop + radius;
var barRadius = top - prevTop;
ctx.beginPath();
ctx.fillStyle = vm.backgroundColor;
ctx.strokeStyle = vm.borderColor;
ctx.lineWidth = borderWidth;
// draw the rounded top rectangle
Chart.helpers.drawRoundedTopRectangle(ctx, left, (top - barRadius + 1), barWidth, bottom - prevTop, barRadius);
ctx.fill();
if (borderWidth) {
ctx.stroke();
}
// restore the original top value so tooltips and scales still work
top = prevTop;
},
});
Next, you will also have to extend the bar chart controller (Chart.controllers.bar
) and overwrite dataElementType
to use the new "rounded rectangle" for the chart instead of a regular rectangle.
Chart.defaults.roundedBar = Chart.helpers.clone(Chart.defaults.bar);
Chart.controllers.roundedBar = Chart.controllers.bar.extend({
dataElementType: Chart.elements.RoundedTopRectangle
});
Lastly, we will modify the chart's config to use the new chart type created above and add a new options property called barRoundness
to control how round the top is (0 is flat, 1 is a semi-circle).
var ctx = document.getElementById("canvas").getContext("2d");
var myBar = new Chart(ctx, {
type: 'roundedBar',
data: {
labels: ["Car", "Bike", "Walking"],
datasets: [{
label: 'Students',
backgroundColor: chartColors.blue,
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
]
}, {
label: 'Teachers',
backgroundColor: chartColors.red,
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
]
}, {
label: 'Visitors',
backgroundColor: chartColors.green,
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
]
}]
},
options: {
responsive: true,
barRoundness: 1,
title: {
display: true,
text: "Chart.js - Bar Chart with Rounded Tops (drawRoundedTopRectangle Method)"
},
}
});
You can see a full working example at this codepen.
Also, in case you want a slightly different "rounded top" look, here is another codepen that uses a different approach to drawing the top (a single quadratic curve).
这篇关于如何为 Bar Chart.js v2 创建圆角条?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何为 Bar Chart.js v2 创建圆角条?
基础教程推荐
- 自定义 XMLHttpRequest.prototype.open 2022-01-01
- Vue 3 – <过渡>渲染不能动画的非元素根节点 2022-01-01
- 直接将值设置为滑块 2022-01-01
- 用于 Twitter 小部件宽度的 HTML/CSS 2022-01-01
- Electron 将 Node.js 和 Chromium 上下文结合起来意味着 2022-01-01
- 如何使用JIT在顺风css中使用布局变体? 2022-01-01
- html表格如何通过更改悬停边框来突出显示列? 2022-01-01
- Chart.js 在线性图表上拖动点 2022-01-01
- 我可以在浏览器中与Babel一起使用ES模块,而不捆绑我的代码吗? 2022-01-01
- 如何使用TypeScrip将固定承诺数组中的项设置为可选 2022-01-01