Add percentage to label badge - doughnut chart.js

随声附和 提交于 2020-04-30 09:17:58

问题


I've been doing a lot of research but I wasn't able to figure out, how to enter percentage into labels badge like this image below.

update: I'm using this laravel wrapper : https://github.com/ConsoleTVs/Charts so was the reason I didn't want to confuse viewers. I just want to know the name of the option.. my code is this:

$perTopicChart = (new AnsweredPerTopic);//->percentageInnerCutout(70);
    $perTopicChart->options([
        "events" => [],
        "legend" => [
            "labels" => [
                "defaultFontFamily" => "Tahoma",
                "fontSize" => 16,
            ],
            "position" => 'bottom'
        ],
        "cutoutPercentage" => 80,
        'tooltips' => [
            "show" => true
        ]
    ])->displayAxes(0);

    // put the labels (keys)
    $perTopicChart->labels($keys->map(function ($q) use ($perTopic) {
        $topic = Topic::find($q);
        $str = $topic->name;
        foreach ($perTopic as $key => $value) {
            if ($key == $q) {
                $str .= ' ' . round($value) . '%';
            }
        }
        return "topic name " . '-'. $topic->id;

    })->push('other'))
    ->options([]);
    // get random color 
    // $color = RandomColor::many(count($keys), array(
    //     'luminosity' => 'bright',
    //     'hue' => ['pink', 'green', 'orange'] // e.g. 'rgb(225,200,20)'
    //     ));
    $color = [
        "#38c172",
        "#9F9",
        "#Fa0",
        "pink",
        "red",
    ];

    $perTopicChart->dataset("Practice per Category", "doughnut", $values->map(function ($q) {
        return round($q);
    })->push($remainingPercenteg))
        ->backgroundColor($color)
        ->options([
            'borderWidth' => 2.5,
        ]);

the first image the current result and the second is what I wanted. thanks in advance.


回答1:


Even I researched a lot, couldn't find anything for this kind of behavior in chartjs library, So come up with a hack.

Hack is something like, Do not let chart js to draw legends, Instead we just get the HTML of legends from chart js library, and put it in our container. By doing this we have full access of legends and we can do whatever we want.

https://jsfiddle.net/1kxenzpr/

const data = [70, 30, 0];
debugger;
var ctx = document.getElementById("myChart").getContext('2d');
var chart = new Chart(ctx, {
  type: 'pie',
  data: {
    labels: ["Green", "Blue", "Gray", "Purple", "Yellow", "Red", "Black"],
    datasets: [{
      backgroundColor: [
        "#2ecc71",
        "#3498db",
        "#95a5a6",
        "#9b59b6",
        "#f1c40f",
        "#e74c3c",
        "#34495e"
      ],
      data: data
    }]
  },
  options: {
    legend: {
      display: false
    },
  }
});
var myLegendContainer = document.getElementById("legend");
myLegendContainer.innerHTML = chart.generateLegend();
var legendItems = myLegendContainer.getElementsByTagName('li');
for (var i = 0; i < legendItems.length; i++) {
  legendItems[i].querySelectorAll('span')[0].innerHTML = data[i] + '%'
}
.container {
  width: 80%;
  margin: 15px auto;
}

[class$="-legend"] {
  list-style: none;
  cursor: pointer;
  padding-left: 0;
}

[class$="-legend"] li {
  display: inline-block;
  padding: 0 5px;
}

[class$="-legend"] li.hidden {
  text-decoration: line-through;
}

[class$="-legend"] li span {
  display: inline-block;
  margin-right: 10px;
  width: 50px;
  font-size: 12px;
  text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>

<div class="container">
  <div>
    <canvas id="myChart"></canvas>
    <div id="legend"></div>
  </div>
</div>



回答2:


No way (By setting X or Y). You should use legendCallback: https://www.chartjs.org/docs/latest/configuration/legend.html#html-legends

In general, your Q does not follow StackOverflow guidelines (This is more a mission, not Q). https://stackoverflow.com/help/how-to-ask

Anyway, this is +- the idea (convert to % by basic JS). To take this step forward you should generate full generate HTML legend (To put a number inside a color div). Related: Custom Legend with ChartJS v2.0

var myData = [4, 9, 5];

var data = {
  labels: ["Africa", "Asia", "Europe"],
  datasets: [{
    label: "Population (millions)",
    backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f"],
    data: myData
  }]
};

/* get total */
const reducer = (accumulator, currentValue) => accumulator + currentValue;
var total = myData.reduce(reducer);

var options = {
  responsive: true,
  title: {
    text: 'Show % calucate on fly',
    position: 'top',
    display: true
  },
  legend: {
    display: true,
    labels: {
      /* generateLabels */
      generateLabels(chart) {
        const data = chart.data;
        if (data.labels.length && data.datasets.length) {
          /* inner loop throw lables */
          return data.labels.map((label, i) => {
            var backgroundColor = data.datasets[0].backgroundColor[i];
            var current = data.datasets[0].data[i];
            var percentage =  ((current * 100) / total).toFixed(2) + '%'; 
            return {
              text: label + " | " + percentage,
              fillStyle: backgroundColor,
              // Extra data used for toggling the correct item
              index: i
            };
          });
        }
        return [];
      }

    },

  },
  scales: {
    xAxes: [{
      display: true
    }],
    yAxes: [{
      display: true
    }]
  }
};


new Chart(document.getElementById("chart"), {
  type: 'pie',
  data: data,
  options: options
});
<canvas id="chart" width="800" height="450"></canvas>

<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>


来源:https://stackoverflow.com/questions/61285234/add-percentage-to-label-badge-doughnut-chart-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!