当一个图例项被关闭/打开时,我如何在一个图表.js饼图中重新分配值?



我已经将数据分布在饼中,使其总数等于100%(我认为lol),如果你不介意,请验证这是正确的。但是当我关闭/打开图例项时,我希望能够重新分配数据。

下面是组件 的示例
import React from "react";
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js";
import { Pie } from "react-chartjs-2";
import ChartDataLabels from "chartjs-plugin-datalabels";
ChartJS.register(ChartDataLabels, ArcElement, Tooltip, Legend);
export const data = [
{ lifetime_viewing_subs: 11497117, name: "US" },
{ lifetime_viewing_subs: 3777651, name: "LATAM" },
{ lifetime_viewing_subs: 2494138, name: "EMEA" }
];
const lifetime_viewing_subs_total = data.map(item => item.lifetime_viewing_subs).reduce((prev, next) => prev + next);
export const pieoptions = {
responsive: true,
plugins: {
legend: {
position: "bottom",
align: "center"
},
datalabels: {
color: function (context) {
return context.dataset.borderColor;
},
anchor: "center",
backgroundColor: function (context) {
return context.dataset.background;
},
borderRadius: 100,
borderWidth: 2,
borderColor: function (context) {
return context.dataset.borderColor;
},
display: function (context) {
var dataset = context.dataset;
var value = dataset.data[context.dataIndex];
console.log("context.dataIndex: ", context.dataIndex); // 0,1,2
console.log("dataset: ", dataset); // the dataset object
console.log("value: ", value); // 0.1403653100534158, 0.647035726341284, 0.21259896360530017

return value;
},
formatter: function (value) {
return Math.round(value * 100).toFixed(0) + "%";
},
font: {
weight: 500,
size: "14rem"
}
}
}
};
export const piedata = {
labels: data.map((s) => s.name),
datasets: [
{
data: data.map((s) => s.lifetime_viewing_subs/lifetime_viewing_subs_total),
backgroundColor: [
"rgba(255, 99, 132, 0.2)",
"rgba(54, 162, 235, 0.2)",
"rgba(255, 206, 86, 0.2)"
],
borderColor: [
"rgba(255, 99, 132, 1)",
"rgba(54, 162, 235, 1)",
"rgba(255, 206, 86, 1)"
],
fill: true,
borderWidth: 1
}
]
};
export function App() {
return (
<Pie options={pieoptions} plugins={[ChartDataLabels]} data={piedata} />
);
}

这是一个操场

Thanks in advance

您可以在formatter函数中计算百分比,如下所示:

formatter: function(value, ctx) {
const max = ctx.dataset.data.reduce((acc, curr, index) => {
const isVisible = ctx.chart.getDataVisibility(index)
if (isVisible) {
acc += curr;
}
return acc;
}, 0)
return Math.round(value * 100 / max).toFixed(0) + "%";
},

生活的例子:

Chart.register(ChartDataLabels);

const data = [{
lifetime_viewing_subs: 11497117,
name: "US"
},
{
lifetime_viewing_subs: 3777651,
name: "LATAM"
},
{
lifetime_viewing_subs: 2494138,
name: "EMEA"
}
];
const lifetime_viewing_subs_total = data
.map((item) => item.lifetime_viewing_subs)
.reduce((prev, next) => prev + next);
const options = {
type: 'pie',
data: {
labels: data.map((s) => s.name),
datasets: [{
label: '# of Votes',
data: data.map((s) => s.lifetime_viewing_subs / lifetime_viewing_subs_total),
backgroundColor: [
"rgba(255, 99, 132, 0.2)",
"rgba(54, 162, 235, 0.2)",
"rgba(255, 206, 86, 0.2)"
],
borderColor: [
"rgba(255, 99, 132, 1)",
"rgba(54, 162, 235, 1)",
"rgba(255, 206, 86, 1)"
],
borderWidth: 1
}]
},
options: {
plugins: {
legend: {
position: "bottom",
align: "center"
},
datalabels: {
color: function(context) {
return context.dataset.borderColor;
},
anchor: "center",
backgroundColor: function(context) {
return context.dataset.background;
},
borderRadius: 100,
borderWidth: 2,
borderColor: function(context) {
return context.dataset.borderColor;
},
display: function(context) {
var dataset = context.dataset;
var value = dataset.data[context.dataIndex];
return value;
},
formatter: function(value, ctx) {
const max = ctx.dataset.data.reduce((acc, curr, index) => {
const isVisible = ctx.chart.getDataVisibility(index)
if (isVisible) {
acc += curr;
}
return acc;
}, 0)
return Math.round(value * 100 / max).toFixed(0) + "%";
},
font: {
weight: 500,
size: "14rem"
}
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js/dist/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels"></script>
</body>

我不明白你想要重新分发的逻辑是什么但无论如何,我写了一些逻辑来重新分发数据,当你turn off/on的传奇项目。

import React from "react";
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js";
import { Pie } from "react-chartjs-2";
import ChartDataLabels from "chartjs-plugin-datalabels";
ChartJS.register(ChartDataLabels, ArcElement, Tooltip, Legend);
export const data = [
{ lifetime_viewing_subs: 11497117, name: "US" },
{ lifetime_viewing_subs: 3777651, name: "LATAM" },
{ lifetime_viewing_subs: 2494138, name: "EMEA" }
];
var defaultLegendClickHandler = ChartJS.defaults.plugins.legend.onClick;
const lifetime_viewing_subs_total = data
.map((item) => item.lifetime_viewing_subs)
.reduce((prev, next) => prev + next);
export const pieoptions = {
responsive: true,
plugins: {
legend: {
onClick(event, legendItem, legend) {
let index = legendItem.index;
let ci = legend.chart;
let tmpData;

legend.chart.data.datasets.forEach((d, i) => {
let dividerSize =  d.data.length;
console.log(d)
d.data.forEach((pie, j) => {
if (index === j) {
// clicked item is it
tmpData = d.data[index];
// you can define here what you want 
// for clicked label
// d.data[j] = 0.20;
// curently i will clear value
d.data[j] = 0;
} else {
// here you can work on other pieces
// you can update next two pieces
// d.data[j] = d.data[j] + 0.22
d.data[j] = pie + 0.2
}
// 

});
});
ci.update();
},
position: "bottom",
align: "center"
},
datalabels: {
color: function (context) {
return context.dataset.borderColor;
},
anchor: "center",
backgroundColor: function (context) {
return context.dataset.background;
},
borderRadius: 100,
borderWidth: 2,
borderColor: function (context) {
return context.dataset.borderColor;
},
display: function (context) {
var dataset = context.dataset;
var value = dataset.data[context.dataIndex];
// console.log("context.dataIndex: ", context.dataIndex); // 0,1,2
// console.log("dataset: ", dataset); // the dataset object
// console.log("value: ", value); // 0.1403653100534158, 0.647035726341284, 0.21259896360530017
return value;
},
formatter: function (value) {
return Math.round(value * 100).toFixed(0) + "%";
},
font: {
weight: 500,
size: "14rem"
}
}
}
};
export const piedata = {
labels: data.map((s) => s.name),
datasets: [
{
data: data.map(
(s) => s.lifetime_viewing_subs / lifetime_viewing_subs_total
),
backgroundColor: [
"rgba(255, 99, 132, 0.2)",
"rgba(54, 162, 235, 0.2)",
"rgba(255, 206, 86, 0.2)"
],
borderColor: [
"rgba(255, 99, 132, 1)",
"rgba(54, 162, 235, 1)",
"rgba(255, 206, 86, 1)"
],
fill: true,
borderWidth: 1
}
]
};
export function App() {
return (
<Pie options={pieoptions} plugins={[ChartDataLabels]} data={piedata} />
);
}

我已经重写了插件/legend/onclick方法,如

plugins: {
legend: {
onClick(event, legendItem, legend) {
let index = legendItem.index;
let ci = legend.chart;
let tmpData;
legend.chart.data.datasets.forEach((d, i) => {
let dividerSize =  d.data.length;
console.log(d)
d.data.forEach((pie, j) => {
if (index === j) {
// clicked item is it
tmpData = d.data[index];
// you can define here what you want 
// for clicked label
// d.data[j] = 0.20;
// curently i will clear value
d.data[j] = 0;
} else {
// here you can work on other pieces
// you can update next two pieces
// d.data[j] = d.data[j] + 0.22
d.data[j] = pie + 0.2
}
// 
});
});
ci.update();
}

你可以随心所欲地redesign动作,工作示例playground

最新更新