Chart.js v2:甜甜圈内部的甜甜圈之间的空间 [英] Chart.js v2: space between doughnut inside doughnut

查看:103
本文介绍了Chart.js v2:甜甜圈内部的甜甜圈之间的空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用chart.js v2.5.0. 我将甜甜圈放入甜甜圈中.

我希望两个甜甜圈( A )之间的距离更大,而又不影响同一个甜甜圈( B )中的切片之间的距离.

请参见下图:

当前,我正在使用属性 borderWidth . 但是,这也会影响 B 的宽度.

请参见以下代码:

options: {
                elements: {
                    arc: {
                        borderWidth: 18,
                    },
                },
                cutoutPercentage: 60,
                responsive: true,
            }

我希望甜甜圈看起来像这样:

解决方案

实现此目的的唯一方法是扩展现有的doughnut控制器,并使用您自己的逻辑来覆盖update方法来确定间距.

下面是一个示例,演示了如何执行此操作.通过此实现,我添加了一个名为datasetRadiusBuffer的新的甜甜圈图选项属性,该属性控制每个数据集之间的空白.

var helpers = Chart.helpers;

// this option will control the white space between embedded charts when there is more than 1 dataset
helpers.extend(Chart.defaults.doughnut, {
  datasetRadiusBuffer: 0
});

Chart.controllers.doughnut = Chart.controllers.doughnut.extend({
  update: function(reset) {
    var me = this;
    var chart = me.chart,
        chartArea = chart.chartArea,
        opts = chart.options,
        arcOpts = opts.elements.arc,
        availableWidth = chartArea.right - chartArea.left - arcOpts.borderWidth,
        availableHeight = chartArea.bottom - chartArea.top - arcOpts.borderWidth,
        minSize = Math.min(availableWidth, availableHeight),
        offset = {
          x: 0,
          y: 0
        },
        meta = me.getMeta(),
        cutoutPercentage = opts.cutoutPercentage,
        circumference = opts.circumference;

    // If the chart's circumference isn't a full circle, calculate minSize as a ratio of the width/height of the arc
    if (circumference < Math.PI * 2.0) {
      var startAngle = opts.rotation % (Math.PI * 2.0);
      startAngle += Math.PI * 2.0 * (startAngle >= Math.PI ? -1 : startAngle < -Math.PI ? 1 : 0);
      var endAngle = startAngle + circumference;
      var start = {x: Math.cos(startAngle), y: Math.sin(startAngle)};
      var end = {x: Math.cos(endAngle), y: Math.sin(endAngle)};
      var contains0 = (startAngle <= 0 && 0 <= endAngle) || (startAngle <= Math.PI * 2.0 && Math.PI * 2.0 <= endAngle);
      var contains90 = (startAngle <= Math.PI * 0.5 && Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 2.5 && Math.PI * 2.5 <= endAngle);
      var contains180 = (startAngle <= -Math.PI && -Math.PI <= endAngle) || (startAngle <= Math.PI && Math.PI <= endAngle);
      var contains270 = (startAngle <= -Math.PI * 0.5 && -Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 1.5 && Math.PI * 1.5 <= endAngle);
      var cutout = cutoutPercentage / 100.0;
      var min = {x: contains180 ? -1 : Math.min(start.x * (start.x < 0 ? 1 : cutout), end.x * (end.x < 0 ? 1 : cutout)), y: contains270 ? -1 : Math.min(start.y * (start.y < 0 ? 1 : cutout), end.y * (end.y < 0 ? 1 : cutout))};
      var max = {x: contains0 ? 1 : Math.max(start.x * (start.x > 0 ? 1 : cutout), end.x * (end.x > 0 ? 1 : cutout)), y: contains90 ? 1 : Math.max(start.y * (start.y > 0 ? 1 : cutout), end.y * (end.y > 0 ? 1 : cutout))};
      var size = {width: (max.x - min.x) * 0.5, height: (max.y - min.y) * 0.5};
      minSize = Math.min(availableWidth / size.width, availableHeight / size.height);
      offset = {x: (max.x + min.x) * -0.5, y: (max.y + min.y) * -0.5};
    }

    chart.borderWidth = me.getMaxBorderWidth(meta.data);
    chart.outerRadius = Math.max((minSize - chart.borderWidth) / 2, 0);
    chart.innerRadius = Math.max(cutoutPercentage ? (chart.outerRadius / 100) * (cutoutPercentage) : 0, 0);
    chart.radiusLength = ((chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount()) + 25;
    chart.offsetX = offset.x * chart.outerRadius;
    chart.offsetY = offset.y * chart.outerRadius;

    meta.total = me.calculateTotal();

    me.outerRadius = chart.outerRadius - (chart.radiusLength * me.getRingIndex(me.index));
    me.innerRadius = Math.max(me.outerRadius - chart.radiusLength, 0);

    // factor in the radius buffer if the chart has more than 1 dataset
    if (me.index > 0) {
      me.outerRadius -= opts.datasetRadiusBuffer;
      me.innerRadius -= opts.datasetRadiusBuffer;
    }

    helpers.each(meta.data, function(arc, index) {
      me.updateElement(arc, index, reset);
    });
  },
});

您可以在此 codepen 中看到一个实时示例.

I am using chart.js v2.5.0. I put doughnut inside doughnut.

I want the disdance between 2 doughnuts(A) to be larger without affecting the distance between slices inside the same doughnut(B).

Please see the following image:

Currently I am using the property borderWidth. However, this also affects the width of B.

Please see the following code:

options: {
                elements: {
                    arc: {
                        borderWidth: 18,
                    },
                },
                cutoutPercentage: 60,
                responsive: true,
            }

I want the doughnuts to look like this:

解决方案

The only way to achieve this is to extend the existing doughnut controller and overwrite the update method with your own logic for determining the spacing.

Here is an example demonstrating how you would do this. With this implementation, I added a new doughnut chart option property called datasetRadiusBuffer that controls the white space between each dataset.

var helpers = Chart.helpers;

// this option will control the white space between embedded charts when there is more than 1 dataset
helpers.extend(Chart.defaults.doughnut, {
  datasetRadiusBuffer: 0
});

Chart.controllers.doughnut = Chart.controllers.doughnut.extend({
  update: function(reset) {
    var me = this;
    var chart = me.chart,
        chartArea = chart.chartArea,
        opts = chart.options,
        arcOpts = opts.elements.arc,
        availableWidth = chartArea.right - chartArea.left - arcOpts.borderWidth,
        availableHeight = chartArea.bottom - chartArea.top - arcOpts.borderWidth,
        minSize = Math.min(availableWidth, availableHeight),
        offset = {
          x: 0,
          y: 0
        },
        meta = me.getMeta(),
        cutoutPercentage = opts.cutoutPercentage,
        circumference = opts.circumference;

    // If the chart's circumference isn't a full circle, calculate minSize as a ratio of the width/height of the arc
    if (circumference < Math.PI * 2.0) {
      var startAngle = opts.rotation % (Math.PI * 2.0);
      startAngle += Math.PI * 2.0 * (startAngle >= Math.PI ? -1 : startAngle < -Math.PI ? 1 : 0);
      var endAngle = startAngle + circumference;
      var start = {x: Math.cos(startAngle), y: Math.sin(startAngle)};
      var end = {x: Math.cos(endAngle), y: Math.sin(endAngle)};
      var contains0 = (startAngle <= 0 && 0 <= endAngle) || (startAngle <= Math.PI * 2.0 && Math.PI * 2.0 <= endAngle);
      var contains90 = (startAngle <= Math.PI * 0.5 && Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 2.5 && Math.PI * 2.5 <= endAngle);
      var contains180 = (startAngle <= -Math.PI && -Math.PI <= endAngle) || (startAngle <= Math.PI && Math.PI <= endAngle);
      var contains270 = (startAngle <= -Math.PI * 0.5 && -Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 1.5 && Math.PI * 1.5 <= endAngle);
      var cutout = cutoutPercentage / 100.0;
      var min = {x: contains180 ? -1 : Math.min(start.x * (start.x < 0 ? 1 : cutout), end.x * (end.x < 0 ? 1 : cutout)), y: contains270 ? -1 : Math.min(start.y * (start.y < 0 ? 1 : cutout), end.y * (end.y < 0 ? 1 : cutout))};
      var max = {x: contains0 ? 1 : Math.max(start.x * (start.x > 0 ? 1 : cutout), end.x * (end.x > 0 ? 1 : cutout)), y: contains90 ? 1 : Math.max(start.y * (start.y > 0 ? 1 : cutout), end.y * (end.y > 0 ? 1 : cutout))};
      var size = {width: (max.x - min.x) * 0.5, height: (max.y - min.y) * 0.5};
      minSize = Math.min(availableWidth / size.width, availableHeight / size.height);
      offset = {x: (max.x + min.x) * -0.5, y: (max.y + min.y) * -0.5};
    }

    chart.borderWidth = me.getMaxBorderWidth(meta.data);
    chart.outerRadius = Math.max((minSize - chart.borderWidth) / 2, 0);
    chart.innerRadius = Math.max(cutoutPercentage ? (chart.outerRadius / 100) * (cutoutPercentage) : 0, 0);
    chart.radiusLength = ((chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount()) + 25;
    chart.offsetX = offset.x * chart.outerRadius;
    chart.offsetY = offset.y * chart.outerRadius;

    meta.total = me.calculateTotal();

    me.outerRadius = chart.outerRadius - (chart.radiusLength * me.getRingIndex(me.index));
    me.innerRadius = Math.max(me.outerRadius - chart.radiusLength, 0);

    // factor in the radius buffer if the chart has more than 1 dataset
    if (me.index > 0) {
      me.outerRadius -= opts.datasetRadiusBuffer;
      me.innerRadius -= opts.datasetRadiusBuffer;
    }

    helpers.each(meta.data, function(arc, index) {
      me.updateElement(arc, index, reset);
    });
  },
});

You can see a live example at this codepen.

这篇关于Chart.js v2:甜甜圈内部的甜甜圈之间的空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆