Как сделать разделитель круглых сегментов в кольцевой диаграмме в chart.js

я пытался сделать выглядят как svg, но без использования svg. bcz в angular, я не нашел ни одной кольцевой диаграммы, похожей на, я нашел одну диаграмму, но это было в jquery, и я не могу использовать jquery. как я могу сделать закругленные края разделителя сегментов этой многоуровневой кольцевой диаграммы я использую chart.js 4 в angular.

Вот пример.

 var config: any= {
      type: 'doughnut',
      data: {
        
          datasets: [{
            label: 'Dataset 1',
              data: [
                
                {
                  value: 50,                 
              },
              {
                  value: 50,                 
              }
                  
              ],
                  backgroundColor: [
                  "#ff3333",
                  "#660000",                
              ],
                  hoverBackgroundColor: [
                "#ff3333",
                "#660000",
              ],
              hoverBackground: NONE_TYPE,
              borderColor:NONE_TYPE,
              hoverBorderColor:NONE_TYPE,
              borderWidth: 0,
              datalabels : {
                display: false
               }
             
          }, {
            label: 'Dataset 2',
              data: [
                {
                  value: 70,                  
              },
              {
                  value: 30,
              }
              ],
                  backgroundColor: [
                  "#00ff00",
                  "#003300",
               ],
                hoverBackgroundColor: [
                "#00ff00",
                "#003300",
             ],
              
               borderColor:NONE_TYPE,
               hoverBorderColor:NONE_TYPE,
               borderWidth: 0,
               datalabels : {
                display: false
               }
               
          }, {
            label: 'Dataset 3', 
              data: [
                {
                 value:40,                    
              },
              {
                value:60,                  
              }
              
               ],
               labels: [
                'green',
                'yellow',
              ] ,
               backgroundColor: [
                  "#1991EB",
                  "#001f4d",
               ],
               hoverBackgroundColor: [
                "#1991EB",
                  "#001a4d",
              ],
              
               borderColor:NONE_TYPE,
               hoverBorderColor:NONE_TYPE,
               borderWidth: 0,
               datalabels : {
                display: false
               },
               
               
          }], 
        
          
      },
      options: {
          responsive: true,
          legend: {
            display: false
          },           
                
        
      }
  };
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
0
72
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Закругленные концы дуг на кольцевой или круговой диаграмме покрываются опцией borderRadius.

Если мы выберем радиус этого закругленного конца равным 15px, мы можем записать это как

    datasets: [{
        //..... data and other dataset options
        borderRadius: [
            {outerStart: 0, outerEnd: 15, innerStart: 0, innerEnd: 15},
            0
        ]
    }]

Очевидно, что для закругления другого конца нужно установить значения outerStart и innerStart. Второе значение массива borderRadius (ноль) соответствует второму значению набора данных, которое является фоном полосы.

Вот фрагмент с вашими данными

const data = {
    datasets: [{
        label: 'Dataset 1',
        data: [50, 50],
        backgroundColor: [
            "#ff3333",
            "#660000",
        ],
        borderRadius: [
            {outerStart: 0, outerEnd: 15, innerStart: 0, innerEnd: 15},
            0
        ],
        borderWidth: 0
    },
    {
        label: 'Dataset 2',
        data: [70, 30],
        backgroundColor: [
            "#00ff00",
            "#003300",
        ],
        borderRadius: [
            {outerStart: 0, outerEnd: 15, innerStart: 0, innerEnd: 15},
            0
        ],
        borderWidth: 0
    },
    {
        label: 'Dataset 3',
        data: [40, 60],
        backgroundColor: [
            "#1991EB",
            "#001a4d",
        ],
        borderRadius: [
            {outerStart: 0, outerEnd: 15, innerStart: 0, innerEnd: 15},
            0
        ],
        borderWidth: 0,
    }]
};

const chart = new Chart(document.querySelector("#myChart"), {
    type: 'doughnut',
    data,
    options: {
        cutout: 60,
        responsive: true,
        radius: "80%"
    }
});
<div style = "max-height:350px">
<canvas id = "myChart" style = "background-color: #000"></canvas>
</div>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.3.0/chart.umd.js"
        integrity = "sha512-CMF3tQtjOoOJoOKlsS7/2loJlkyctwzSoDK/S40iAB+MqWSaf50uObGQSk5Ny/gfRhRCjNLvoxuCvdnERU4WGg= = "
        crossorigin = "anonymous" referrerpolicy = "no-referrer"></script>

С этим есть несколько проблем:

  • фон не идеален, под закругленными концами фон холста, а не второй цвет, который должен быть на фоне полос
  • второй элемент, который должен действовать как фон, также создает всплывающую подсказку при наведении, которую необходимо отключить.
  • радиус закругленного конца должен быть задан заранее, и изменение размера холста может привести к неадекватным значениям (хотя может быть реализовано обновление).

Чтобы охватить эти случаи, я реализовал пользовательский DoughnutController, см. документы, называемый DoughnutWithRoundEnds, с идентификатором doughnut_round_ends, который расширяет стандартный doughnut тремя вариантами набора данных:

  • roundStart и roundEnd, (значение по умолчанию true для каждого), логическое значение для каждого значения (радиус границы задавать не нужно, он вычисляется автоматически с учетом текущего размера дуги при рисовании)
  • overallBackgroundColor - неактивный цвет фона полосы - что позволит использовать только одно значение в сочетании с установкой окружности

const _drawArcElement = Chart.ArcElement.prototype.draw;
class DoughnutWithRoundEnds extends Chart.DoughnutController{
    static id = "doughnut_round_ends";

    updateElements(arcs, start, count, mode) {
        super.updateElements(arcs, start, count, mode);
        const dataset = this.getDataset();
        const overallBackgroundColor = dataset.overallBackgroundColor ??
            this.options.overallBackgroundColor;
        let roundEnd = this.getDataset().roundEnd ?? this.options.roundEnd ?? true;
        if (!Array.isArray(roundEnd)){
            roundEnd = Array(arcs.length).fill(roundEnd);
        }
        let roundStart = dataset.roundStart ?? this.options.roundStart ?? true;
        if (!Array.isArray(roundStart)){
            roundStart = Array(arcs.length).fill(roundStart);
        }
        if (overallBackgroundColor && roundEnd.length > 0){
            arcs.forEach((arc, i) => {
                let borderRadius = 0;
                if (roundEnd[i] || roundStart[i]){
                    const r = Math.ceil((arc.outerRadius - arc.innerRadius)/2),
                        rStart = roundStart[i] ? r : 0,
                        rEnd = roundEnd[i] ? r : 0;
                    borderRadius = {
                        outerStart: rStart,
                        outerEnd: rEnd,
                        innerStart: rStart,
                        innerEnd: rEnd
                    };
                }
                if (i === 0 && overallBackgroundColor){
                    arc.draw = function(ctx){
                        const backgroundColor = this.options.backgroundColor,
                            startAngle = this.startAngle,
                            endAngle = this.endAngle;
                        this.options.backgroundColor = overallBackgroundColor;
                        this.options.borderRadius = 0;
                        this.startAngle = 0;
                        this.endAngle = 2*Math.PI;
                        _drawArcElement.call(this, ctx);
                        this.options.backgroundColor = backgroundColor;
                        this.startAngle = startAngle;
                        this.endAngle = endAngle;
                        this.options.borderRadius = borderRadius;
                        _drawArcElement.call(this, ctx);
                    }
                }
                else{
                    this.options.borderRadius = borderRadius;
                }
            });
        }
    }
}

Chart.register(DoughnutWithRoundEnds);

const data = {
    datasets: [{
        label: 'Dataset 1',
        data: [50],
        circumference: [50/100*360],
        backgroundColor: [
            "#ff3333"
        ],
        //roundStart: [true], //default
        // roundEnd: [true], // default
        overallBackgroundColor: "#660000",
        borderWidth: 0
    },
    {
        label: 'Dataset 2',
        data: [70],
        circumference: [70/100*360],
        backgroundColor: [
            "#00ff00"
        ],
        overallBackgroundColor: "#003300",
        borderWidth: 0
    },
    {
        label: 'Dataset 3',
        data: [40],
        circumference: [40/100*360],
        backgroundColor: [
            "#1991EB",
        ],
        overallBackgroundColor: "#001a4d",
        borderWidth: 0
    }]
};

const chart = new Chart(document.querySelector("#myChart"), {
    type: 'doughnut_round_ends',
    data,
    options: {
        cutout: 60,
        responsive: true,
        radius: "80%",
        //roundStart: false // for all datasets
    }
});
<div style = "max-height:350px">
<canvas id = "myChart" style = "background-color: #000"></canvas>
</div>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.3.0/chart.umd.js"
        integrity = "sha512-CMF3tQtjOoOJoOKlsS7/2loJlkyctwzSoDK/S40iAB+MqWSaf50uObGQSk5Ny/gfRhRCjNLvoxuCvdnERU4WGg= = "
        crossorigin = "anonymous" referrerpolicy = "no-referrer"></script>

Эта версия также работает с двумя (или более) значениями, как и в первом случае, если второе актуально, а не только для фона: jsFiddle.

Большое спасибо за вашу помощь, я отказался от этой задачи, потому что это казалось мне невозможным.

Prince Bhati 02.05.2023 03:36

Другие вопросы по теме