can you help me. i want show my data in percententage value. but my label is undefined. how i show my label to?
this my chart
var options = {
tooltips: {
custom: true
},
plugins: {
datalabels: {
display: true,
formatter: (value, ctx) => {
let datasets = ctx.chart.data.datasets;
if (datasets.indexOf(ctx.dataset) === datasets.length - 1) {
let sum = datasets[0].data.reduce((a, b) => a + b, 0);
let percentage = Math.round((value / sum) * 100) + '%';
return percentage;
} else {
return percentage;
}
},
color: '#fff',
}
}
};
var ctx = document.getElementById("pie-chart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'pie',
data: {
datasets: data
},
options: options
});
Labels array is not supposed to be in the dataset itself but is supposed to be in the main data object like so:
var data = [{
data: [50, 55, 60, 33],
backgroundColor: [
"#4b77a9",
"#5f255f",
"#d21243",
"#B27200"
],
borderColor: "#fff"
}];
var options = {
plugins: {
datalabels: {
formatter: (value, ctx) => {
let sum = 0;
let dataArr = ctx.chart.data.datasets[0].data;
dataArr.map(data => {
sum += data;
});
let percentage = (value * 100 / sum).toFixed(2) + "%";
return percentage;
},
color: '#fff',
}
}
};
var ctx = document.getElementById("pie-chart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'pie',
data: {
labels: ["India", "China", "US", "Canada"],
datasets: data
},
options: options
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#0.4.0/dist/chartjs-plugin-datalabels.min.js"></script>
<canvas id="pie-chart"></canvas>
Related
I'm using chart.js to graph my data.
I'm wondering if I can show the flag image/icon PNG for the labels.
function drawChart(obj, columnName, type = 'bar', selectedVal){
var ajax = $.ajax({url: '/query/' + obj + '/'+ columnName + '/' + selectedVal });
ajax.done(function (response) {
console.log('Response from API >>',response);
$('.lds-ripple').fadeOut();
var selector = `chart-${columnName}`;
var chartHtml = `<div class="col-sm-6"><canvas class="chart" id="${selector}" height="200"></canvas></div>`;
$('.charts').append(chartHtml);
keys = [];
values = [];
var length = 0
$.each(response, function(key,val) {
//console.log(key+val);
length++;
if(length<15){
keys.push(key);
values.push(val);
}
});
var showLegend = false;
if(type == 'doughnut' || type == 'radar' || type == 'polarArea' || type == 'pie'){
showLegend = true;
}
let chart = document.getElementById(selector).getContext('2d');
let xAxisTitle = columnName;
var sumOfAllValues = values.reduce((a, b) => a + b, 0);
Chart.defaults.global.defaultFontColor = "#fff";
var ticksDisplay = true;
if(columnName == 'country'){
ticksDisplay = false;
}
const images = ['https://i.stack.imgur.com/2RAv2.png', 'https://i.stack.imgur.com/Tq5DA.png', 'https://i.stack.imgur.com/3KRtW.png', 'https://i.stack.imgur.com/iLyVi.png'];
new Chart(chart, {
type: type, // bar, horizontalBar, pie, line, doughnut, radar, polarArea
plugins: [{
afterDraw: chart => {
var ctx = chart.chart.ctx;
var xAxis = chart.scales['x-axis-0'];
var yAxis = chart.scales['y-axis-0'];
xAxis.ticks.forEach((value, index) => {
var x = xAxis.getPixelForTick(index);
var y = yAxis.getPixelForTick(index);
var image = new Image();
image.src = images[index],
ctx.drawImage(image, x - 12, yAxis.bottom + 10);
// ctx.drawImage(image, x + 12, yAxis.left - 10);
});
}
}],
data:{
labels: keys,
datasets:[{
label:'Count',
data:values,
borderWidth:2,
hoverBorderWidth:2,
hoverBorderColor:'#fff',
color:'#fff',
backgroundColor: neonBgColors,
borderColor: neonBgBorders,
defaultFontColor: 'white'
}
]
},
options:{
title:{
display:true,
fontSize: 20,
text: columnName + '(' + sumOfAllValues + ')'
},
legend:{
display:showLegend,
position:'right',
labels:{
fontColor:'#000'
}
},
scales: {
xAxes: [{
ticks: {
precision:0,
beginAtZero: true
},
scaleLabel: {
display: true,
labelString: xAxisTitle + ' (' + sumOfAllValues + ')'
}
}],
yAxes: [{
ticks: {
precision:0,
beginAtZero: true,
display: ticksDisplay,
},
scaleLabel: {
display: true,
// labelString: 'Visitor Count'
}
}]
},
layout: {
padding: {
bottom: 30
}
},
}
});
});
}
I kept getting
I adapted the code of this answer and came up with the following solution for your case.
const labels = ['Red Vans', 'Blue Vans', 'Green Vans', 'Gray Vans'];
const images = ['https://i.stack.imgur.com/2RAv2.png', 'https://i.stack.imgur.com/Tq5DA.png', 'https://i.stack.imgur.com/3KRtW.png', 'https://i.stack.imgur.com/iLyVi.png']
.map(png => {
const image = new Image();
image.src = png;
return image;
});
const values = [48, 56, 33, 44];
new Chart(document.getElementById("myChart"), {
type: "horizontalBar",
plugins: [{
afterDraw: chart => {
var ctx = chart.chart.ctx;
var xAxis = chart.scales['x-axis-0'];
var yAxis = chart.scales['y-axis-0'];
yAxis.ticks.forEach((value, index) => {
var y = yAxis.getPixelForTick(index);
ctx.drawImage(images[index], xAxis.left - 40, y - 10);
});
}
}],
data: {
labels: labels,
datasets: [{
label: 'My Dataset',
data: values,
backgroundColor: ['red', 'blue', 'green', 'lightgray']
}]
},
options: {
responsive: true,
layout: {
padding: {
left: 50
}
},
legend: {
display: false
},
scales: {
yAxes: [{
ticks: {
display: false
}
}],
xAxes: [{
ticks: {
beginAtZero: true
}
}],
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="myChart" height="90"></canvas>
I am new in JavaScript and I really want to know that how can we display data in form of percentage by fetching percentage data through doughnut chart using JS
<div class="block-text">
<div class="flex-chart"> <div class="box-file"></div><p class="spacing">abc</p>
<p id = "count">20%</p></div>
<div class="flex-chart"> <div class="box-url"></div><p class="spacing">xyz</p>
<p>30%</p>
</div>
</div>
Here is the Doughnut Chart JS code:
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.4"></script>
<!-- <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#0.7.0"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.0.0/chartjs-plugin-datalabels.min.js"></script>
<script>
// setup
const data = {
//labels: ['xyz', 'abc'],
datasets: [{
// label: 'Weekly Sales',
data: [12, 20],
backgroundColor: [
'rgb(254, 214, 10)',
'rgb(255, 90, 48)'
],
borderColor: [
"#ffffff",
],
borderWidth: 1
}]
};
// config
const config = {
type: 'doughnut',
data,
options: {
plugins: {
datalabels: {
formatter: (value, ctx) => {
let datasets = ctx.chart.data.datasets;
if (datasets.indexOf(ctx.dataset) === datasets.length - 1) {
var sum = datasets[0].data.reduce((a, b) => a + b, 0);
var percentage = Math.round((value / sum) * 100) + '%';
return percentage;
} else {
return percentage;
}
},
color: '#fff',
}
}
}
}
// render init block
const myChart = new Chart(
document.getElementById('chart'),
config
);
Now I want to display Percentage to get it from doughnut chart percentage variable and post it on 'abc' tag
abc
20%
I want percentage data in replace of 20% because 20% is static at this time
Check this code may be it will help you.
var data = [{
data: [50, 55, 60, 33],
labels: ["India", "China", "US", "Canada"],
backgroundColor: [
"#4b77a9",
"#5f255f",
"#d21243",
"#B27200"
],
borderColor: "#fff"
}];
var options = {
tooltips: {
enabled: false
},
plugins: {
datalabels: {
formatter: (value, ctx) => {
let datasets = ctx.chart.data.datasets;
if (datasets.indexOf(ctx.dataset) === datasets.length - 1) {
let sum = datasets[0].data.reduce((a, b) => a + b, 0);
let percentage = Math.round((value / sum) * 100) + '%';
return percentage;
} else {
return percentage;
}
},
color: '#fff',
}
}
};
var ctx = document.getElementById("pie-chart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'pie',
data: {
datasets: data
},
options: options
});
JSFIDDLE
I have few values like A and B now I have pair of them I am showing them on chart-js like this
Now for my use case, I am calculating the third value using A and B. E.g a=100 and b=50, and dividing them will give me c=2.0. Now I want to show this c value on top of A and B bar as a common label like this
"chart.js": "^3.3.0",
react-js
const newChartInstance = new Chart(chartContainer.current, {
type: "bar",
options: {
scales: {
yAxes: [
{
ticks: {
beginAtZero: true,
},
},
],
},
...config.options,
onClick: (e) => {
const points = newChartInstance.getElementsAtEventForMode(
e,
"nearest",
{ intersect: true },
true
);
if (points.length) {
const firstPoint = points[0];
var type =
newChartInstance.data.datasets[firstPoint.datasetIndex].label;
var label = newChartInstance.data.labels[firstPoint.index];
var value =
newChartInstance.data.datasets[firstPoint.datasetIndex].data[
firstPoint.index
];
// This is the result that you will use to breakdown the chart
//console.log(label, value, type);
dispatch(setClickedBar({ label, value, type, tile: props.tile }));
}
},
},
data: data,
});
You can use a custom plugin for that:
var options = {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: 'red'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
backgroundColor: 'blue'
}
]
},
options: {
plugins: {
customValue: {
name: 'ROI',
}
}
},
plugins: [{
id: 'customValue',
afterDraw: (chart, args, opts) => {
const {
ctx,
data: {
datasets
},
_metasets
} = chart;
datasets[0].data.forEach((dp, i) => {
let barValue = `${(datasets[1].data[i] + dp) / 2}%`;
const lineHeight = ctx.measureText('M').width;
const textVal = opts.name || 'fill'
ctx.textAlign = 'center';
ctx.fillText(barValue, _metasets[0].data[i].x, (_metasets[0].data[i].y - lineHeight * 1.5), _metasets[0].data[i].width);
ctx.fillText(textVal, _metasets[0].data[i].x, (_metasets[0].data[i].y - lineHeight * 3), _metasets[0].data[i].width);
});
}
}]
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.4.1/chart.js"></script>
</body>
I'm trying to show weight_id retrieved from mysql data in a chart.js tooltip (shown as (weight_ids[index]) in the image). And later, I intend to show a modal instead of a tooltip to let users update or delete that data. I presume I cannot achieve that without linking the linechart's point data with id stored in mysql. How can I incorporate this id data?
I would appreciate any help very much.
enter image description here
My code is as follows:
<canvas id="myChart"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.4/dist/Chart.min.js"></script>
{{-- グラフを描画--}}
<script>
//ラベル
const labels = #json($date_labels);
// id
const weight_ids = #json($weight_ids);
//体重ログ
const weight_logs = #json($weight_logs);
const aryMax = function(a, b) {
return Math.max(a, b);
};
const aryMin = function(a, b) {
return Math.min(a, b);
};
let min_label = Math.floor((weight_logs).reduce(aryMin) - 0.5);
let max_label = Math.ceil((weight_logs).reduce(aryMax) + 0.5);
console.log(weight_ids);
console.log(weight_logs);
console.log(min_label, max_label);
//グラフを描画
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data : {
labels: labels, // x軸ラベル
datasets: [
{
label: `Weight (weight_ids[index])`,
data: weight_logs,
tension: 0,
borderColor: "rgba(37,78,255,1)",
backgroundColor: "rgba(0,0,0,0)",
pointRadius: 3
}
]
},
options: {
title: {
display: false,
text: ''
},
legend: {
display: false,
},
scales: {
yAxes: [
{
ticks: {
min: min_label, // ラベル最小値
max: max_label, // ラベル最大値
},
scaleLabel: {
display: true,
fontSize: 16,
labelString: '体重 (kg)'
}
}
],
},
hover: {
mode: 'point'
},
onClick: function clickHandler(evt) {
var firstPoint = myChart.getElementAtEvent(evt)[0];
if (firstPoint) {
var label = myChart.data.labels[firstPoint._index];
var value = myChart.data.datasets[firstPoint._datasetIndex].data[firstPoint._index];
console.log(label);
console.log(value);
if (value) {
$('#weidhtModal').modal('show');
}
}
}
}
});
</script>
Thank you!
I found a way to retrieve weight_id using the following function.
onClick: function clickHandler(evt, activeElements) {
if (activeElements.length) {
var element = this.getElementAtEvent(evt);
var index = element[0]._index;
var _datasetIndex = element[0]._datasetIndex;
var weightId = weight_ids[index];
var weightLog = weight_logs[index];
console.log(index);
console.log(weightId);
console.log(this.data.labels[index]);
console.log(weightLog);
}
}
I'm trying to get chartjs to hide pie slices on click; the same behavior seen when clicking on the legend.
Here is the code I'm using - I commented out the code that actually removes the data from the chart since it doesn't re-render the pie chart correctly.
const values = [50, 55, 60, 33];
const data = {
labels: ["India", "China", "US", "Canada"],
datasets: [{
data: values,
backgroundColor: [
"#4b77a9",
"#5f255f",
"#d21243",
"#B27200"
],
borderColor: "#fff"
}]
};
const options = {
tooltips: {
enabled: false
},
legend: {
enabled: true,
position: 'bottom'
},
animation: false,
onClick: handleClick,
plugins: {
datalabels: {
formatter: (value = 0, ctxx) => {
const sum = values.reduce((acc, val = 0) => (acc + val), 0);
return `${(value * 100 / sum).toFixed(2)}%`;
},
color: '#fff',
}
}
};
const ctx = document.getElementById("pie-chart").getContext('2d');
const myChart = new Chart(ctx, {
type: 'pie',
data,
options: options
});
function handleClick(e, slice) {
setTimeout(() => {
const legend = myChart.legend.legendItems;
if (slice && slice[0]) {
// get clicked on slice index
const sliceIndex = slice[0]._index;
// Removing the data "really" messes up the chart
// myChart.data.labels.splice(sliceIndex, 1);
// myChart.data.datasets[0].data.splice(sliceIndex, 1);
legend[sliceIndex].hidden = true;
chart.update();
}
const visibleSlices = legend.filter(l => !l.hidden);
console.log('visible slices', visibleSlices);
});
}
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#0.4.0/dist/chartjs-plugin-datalabels.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="pie-chart"></canvas>
It seems like setting the hidden flag then updating the chart should work because that's what the plugin is doing: https://github.com/chartjs/Chart.js/blob/master/src/plugins/plugin.legend.js#L20-L30.
The code below is hiding a slice by the index
myChart.getDatasetMeta(0).data[sliceIndex].hidden = true
const values = [50, 55, 60, 33];
const data = {
labels: ["India", "China", "US", "Canada"],
datasets: [{
data: values,
backgroundColor: [
"#4b77a9",
"#5f255f",
"#d21243",
"#B27200"
],
borderColor: "#fff"
}]
};
const options = {
tooltips: {
enabled: false
},
legend: {
enabled: true,
position: 'bottom'
},
animation: false,
onClick: handleClick,
plugins: {
datalabels: {
formatter: (value = 0, ctxx) => {
const sum = values.reduce((acc, val = 0) => (acc + val), 0);
return `${(value * 100 / sum).toFixed(2)}%`;
},
color: '#fff',
}
}
};
const ctx = document.getElementById("pie-chart").getContext('2d');
const myChart = new Chart(ctx, {
type: 'pie',
data,
options: options
});
function handleClick(e, slice) {
setTimeout(() => {
const legend = myChart.legend.legendItems;
if (slice && slice[0]) {
const sliceIndex = slice[0]._index;
myChart.getDatasetMeta(0).data[sliceIndex].hidden = true
myChart.update();
}
});
}
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#0.4.0/dist/chartjs-plugin-datalabels.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="pie-chart"></canvas>