如何为 Bar Chart.js v2 创建圆角条?

新手上路,请多包涵

尝试按照本文中提供的 jsFiddle 中显示的那样 对条形图上的条进行四舍五入。这是针对版本 1 的。

在我使用的图表中,无法加载对 extend 的引用 Chart.types.Bar.extend 使脚本崩溃。

如果我使用默认选项,图表加载没有问题。我必须将 Chart.types.Bar.extend 放在最后,以便默认选项正确加载。运行并全屏查看。

我尝试使用我的 Chart.js 2.4.0 版本来实现它。

Chrome 报告:

未捕获的类型错误:无法读取未定义的 chart.js 的属性“扩展”

这段代码甚至不会在这里运行。为什么会这样?有人可以帮助我吗?

此代码适用于旧版本的 Chart.js 1.0。谁能进一步展示这如何与 Chart.js 2.0 版一起使用?谢谢你。

 $(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>

原文由 mcv 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 319
1 个回答

您尝试使用的代码实际上适用于 chart.js v1,正如您发现的那样,不适用于 chart.js v2(这几乎是完整的 chart.js 重写)。

要在 chart.js v2 中获得相同的结果,您需要扩展 Chart.elements.Rectangle 并覆盖它的 draw 方法以绘制圆顶。已经有一个绘制圆角矩形的 chart.js 辅助方法 ( Chart.helpers.drawRoundedRectangle ),因此我们将稍微修改它并创建一个新的辅助方法,它只会绘制一个圆顶(而不是所有边) .

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

接下来,您还必须扩展条形图控制器 ( 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, {
  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)"
    },
  }
});

您可以在这个 codepen 看到一个完整的工作示例。

此外,如果您想要稍微不同的“圆顶”外观,这里是另一个 代码笔,它使用不同的方法来绘制顶部(一条二次曲线)。

原文由 jordanwillis 发布,翻译遵循 CC BY-SA 3.0 许可协议

推荐问题