Hello everyone I am a newbie in using chart.js package, is there a way I can create is king of chart?
Yes, it is possible.
There might be already a plugin, that can achieve this (but I don't know any, but I didn't really look), so you could look for one,
Or you could simply write your own plugin, with a few lines of code
Here a demo, how I would do this, with an inline plugin:
(three charts with 3 different percentages)
var arrowPlugin = {
id: 'arrowPlugin',
afterDraw: (chart, args, options) => {
const { ctx } = chart;
let midX = chart.width / 2;
let midY = chart.height;
let arrowLength = chart.height / 2;
let text = `${options.value * 100}%`;
let textSize = ctx.measureText(text);
ctx.save();
ctx.save();
ctx.translate(midX, midY);
ctx.rotate( (Math.PI * options.value) - Math.PI /2);
ctx.strokeStyle = options.arrowColor;
ctx.fillStyle = options.arrowColor;
ctx.lineCap = 'butt';
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(0, - arrowLength * 3 / 4 + 3)
ctx.lineTo(0, - arrowLength * 6 / 4);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(0, - arrowLength * 6 / 4 - 4)
ctx.lineTo(5, - arrowLength * 6 / 4 + 10)
ctx.lineTo(-5, - arrowLength * 6 / 4 + 10)
ctx.closePath();
ctx.fill()
ctx.fillStyle = options.triangleColor;
ctx.beginPath();
ctx.moveTo(0, -midY + 25)
ctx.lineTo(-10, -midY + 10)
ctx.lineTo(10, -midY + 10)
ctx.closePath()
ctx.fill();
ctx.restore();
ctx.fillStyle = options.textColor;
ctx.font = "50px Arial";
ctx.fillText(text, midX - textSize.width * 1.5, midY - 25);
ctx.restore();
},
defaults: {
// set here the percentage
value:.50,
arrowColor: 'black',
textColor: 'black',
triangleColor: 'black'
}
}
var options1 = {
type: 'doughnut',
data: {
datasets: [{
data: [20, 50, 30],
backgroundColor: [
'rgba(231, 76, 60, 1)',
'rgba(255, 164, 46, 1)',
'rgba(46, 204, 113, 1)'
],
borderColor: [
'rgba(255, 255, 255 ,1)',
'rgba(255, 255, 255 ,1)',
'rgba(255, 255, 255 ,1)'
],
borderWidth: 0
}]},
options: {
cutout: 33,
rotation: -90,
circumference: 180,
maintainAspectRatio: false,
legend: { display: false },
plugins:{
tooltip: { enabled: false },
}
},
plugins:[arrowPlugin]
}
var options2 = {
type: 'doughnut',
data: {
datasets: [{
data: [20, 50, 30],
backgroundColor: [
'rgba(231, 76, 60, 1)',
'rgba(255, 164, 46, 1)',
'rgba(46, 204, 113, 1)'
],
borderColor: [
'rgba(255, 255, 255 ,1)',
'rgba(255, 255, 255 ,1)',
'rgba(255, 255, 255 ,1)'
],
borderWidth: 0
}]},
options: {
cutout: 33,
rotation: -90,
circumference: 180,
maintainAspectRatio: false,
legend: { display: false },
plugins:{
tooltip: { enabled: false },
// override default percentage
arrowPlugin: { value: .20 }
}
},
plugins:[arrowPlugin]
}
var options3 = {
type: 'doughnut',
data: {
datasets: [{
data: [20, 50, 30],
backgroundColor: [
'rgba(231, 76, 60, 1)',
'rgba(255, 164, 46, 1)',
'rgba(46, 204, 113, 1)'
],
borderColor: [
'rgba(255, 255, 255 ,1)',
'rgba(255, 255, 255 ,1)',
'rgba(255, 255, 255 ,1)'
],
borderWidth: 0
}]},
options: {
cutout: 33,
rotation: -90,
circumference: 180,
maintainAspectRatio: false,
legend: { display: false },
plugins:{
tooltip: { enabled: false },
// override default percentage
arrowPlugin: { value: .70 }
}
},
plugins:[arrowPlugin]
}
const chart1 = document.getElementById('chart1')
new Chart(chart1, options1);
const chart2 = document.getElementById('chart2')
new Chart(chart2, options2);
const chart3 = document.getElementById('chart3')
new Chart(chart3, options3);
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<div style="width:500px;height:184px">
<canvas id="chart1" width="500" height="184"></canvas>
<canvas id="chart2" width="500" height="184"></canvas>
<canvas id="chart3" width="500" height="184"></canvas>
<div>
the percentage is currently set in the inline plugin-options, default value is set to .5 = 50% (valid range 0 - 1 = 0% - 100%).
Related
I wanna set double yAxis, so I wrote down the code like below
const data = {
labels: ['a', 'b', 'c', 'd', 'e'],
datasets: [
{
type: 'bar',
label: this.$t('numberOfBuilding'),
data: [100, 20, 30, 5, 5],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(255, 159, 64, 0.2)',
'rgba(255, 205, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(54, 162, 235, 0.2)'
],
borderColor: ['rgb(255, 99, 132)', 'rgb(255, 159, 64)', 'rgb(255, 205, 86)', 'rgb(75, 192, 192)', 'rgb(54, 162, 235)'],
borderWidth: 1,
yAxisId: 'y'
},
// {
// type: 'line',
// fill: true,
// label: this.$t('output') + '(' + this.$t('criteriaMonth') + ')',
// data: [200, 500, 600, 800, 1000],
// borderColor: 'rgba(255, 201, 14, 1)',
// backgroundColor: 'rgba(255, 201, 14, 0.5)',
// lineTension: 0.2,
// yAxisId: 'y1'
// },
{
type: 'line',
fill: true,
label: this.$t('output') + '(' + this.$t('sum') + ')',
data: [300, 100, 700, 249, 588],
borderColor: 'rgba(55, 201, 14, 1)',
backgroundColor: 'rgba(55, 201, 14, 0.5)',
lineTension: 0.2,
yAxisId: 'y1'
}
]
}
const config = {
type: 'scatter',
data: data,
options: {
scales: {
y: {
beginAtZero: true,
position: 'left'
},
y1: {
position: 'right',
grid: {
drawOnChartArea: false
}
}
}
}
}
but it doesn't work properly
yAxis which id is 'y1' is at left and datasets[0] which has 'y' as yAxisId presents with 'y1' axis
it seems like yAxisId doesn't connect well with their own datasets
See the below pictures
[result of above code]
(https://i.stack.imgur.com/0moGR.png)
but my another code is work well I don't know what different it is
here's my another code which works well
const data = {
labels: [
1 + this.$t('month'),
2 + this.$t('month'),
3 + this.$t('month'),
4 + this.$t('month'),
5 + this.$t('month'),
6 + this.$t('month'),
7 + this.$t('month'),
8 + this.$t('month'),
9 + this.$t('month'),
10 + this.$t('month'),
11 + this.$t('month'),
12 + this.$t('month')
],
datasets: [
{
type: 'bar',
label: this.$t('totalConsumption') + '(' + this.unit + ')',
data: this.consumptionData,
borderColor: 'rgb(255, 99, 132)',
backgroundColor: 'rgba(255, 99, 132, 0.2)',
yAxisID: 'y'
},
{
type: 'line',
label: this.$t('temperatureAVG') + '(℃)',
data: this.temperatureData,
fill: false,
borderColor: 'rgb(54, 162, 235)',
yAxisID: 'y1'
}
]
}
const config = {
type: 'scatter',
data: data,
options: {
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
position: 'left'
},
y1: {
position: 'right',
grid: {
drawOnChartArea: false
}
}
}
}
}
In the first code, the option name is wrong. You are using yAxisId but the correct one is yAxisID (as in the second sample), id must be uppercase
I am trying to use echarts bar https://echarts.apache.org/examples/en/editor.html?c=bar-label-rotation&lang=ts for displaying data . The problem I have is when trying to add four different bars to a chart I get error: [ECharts] Unkown series undefined. It works fine when there is only one bar. Here is my code:
this.chartOptions = {
grid: {
top: 20,
bottom: 90,
right: 5,
left: 60
},
legend: {
data: [
'Positive Capacity'
'Negative Capacity'
'Positive Energy'
'Negative Energy'
]
},
tooltip: {
trigger: 'axis',
formatter: (val) => `
<div>${format.formatTime('dd.MM.yyyy hh:mm', val[0].data[0])}</div>
<div>${val[0].marker}<span style="float:right"> ${val[0].data[1]} kW</span></div>
`
},
xAxis: {
type: 'time',
name: this.chartTranslations.xAxis,
nameLocation: 'middle',
nameGap: 80,
axisLabel: {
rotate: 45,
formatter: (val) => format.formatTime('dd.MM.yy hh:mm', val)
}
},
yAxis: {
type: 'value',
name: this.chartTranslations.yAxis,
nameLocation: 'middle',
nameGap: 50,
scale: true,
boundaryGap: ['2%', '2%'],
axisLabel : {
formatter: (val) => this.isMegaWatts ? (val/1000 + ' MW') : (val + ' kW')
},
},
series: [
{
name: 'Positive Capacity'
type: 'bar',
barGap: 10,
emphasis: {
focus: 'series'
},
itemStyle: {
color: new graphic.LinearGradient(0, 0, 0, 2.5, [
{
offset: 0,
color: 'rgba(45, 159, 195, 1)'
},
{
offset: 1,
color: 'rgba(255, 255, 255, 0)'
}
])
},
data: this.positiveCapacity
},
{
name: 'Negative Capacity',
type: 'bar',
barGap: 10,
emphasis: {
focus: 'series'
},
itemStyle: {
color: new graphic.LinearGradient(5, 5, 0, 2.5, [
{
offset: 0,
color: 'rgba(45, 159, 195, 1)'
},
{
offset: 1,
color: 'rgba(255, 255, 255, 0)'
}
])
},
data: this.negativeCapacity
},
{
name: 'Positive Energy',
type: 'bar',
barGap: 10,
emphasis: {
focus: 'series'
},
itemStyle: {
color: new graphic.LinearGradient(10, 10, 0, 2.5, [
{
offset: 0,
color: 'rgba(45, 159, 195, 1)'
},
{
offset: 1,
color: 'rgba(255, 255, 255, 0)'
}
])
},
data: this.positiveEnergy
},
{
name: 'Positive Capacity',
type: 'bar',
barGap: 10,
emphasis: {
focus: 'series'
},
itemStyle: {
color: new graphic.LinearGradient(20, 20, 0, 2.5, [
{
offset: 0,
color: 'rgba(45, 159, 195, 1)'
},
{
offset: 1,
color: 'rgba(255, 255, 255, 0)'
}
])
},
data: this.negativeEnergy
}
]
};
Then later setting content with: Echarts.setOption(this.chartOptions);
Thanks for any help or insight.
I am having trouble displaying small values in my chart.js chart. My issue is very similar to a question asked here:
How to show small values in Flot Pie chart
Does anyone know if there is a workaround in chart.js?
You can use chartjs-plugin-datalabels and define a dataset with same data but weight: 0 for displaying small values outside of the chart.
{
data: data,
weight: 0,
borderWidth: 20,
datalabels: {
formatter: v => v < 5 ? v : ''
}
}
Then also add a datalabels.formatter to the original dataset and make sure, it returns an empty string for small values.
datalabels: {
textAlign: 'center',
formatter: v => v < 5 ? '' : v
}
Please take a look at the runnable code below and see how it works.
const data = [48, 56, 3, 1, 44];
Chart.register(ChartDataLabels);
new Chart('myChart', {
type: 'pie',
data: {
labels: ['red', 'blue', 'green', 'purple', 'gray'],
datasets: [{
data: data,
weight: 0,
borderWidth: 20,
datalabels: {
formatter: v => v < 5 ? v : ''
}
},
{
label: 'My Dataset',
data: data,
backgroundColor: ['rgba(255, 0, 0, 0.2)', 'rgba(0, 0, 255, 0.2)', 'rgba(0, 255, 0, 0.2)', 'rgba(145, 90, 185, 0.2)', 'rgba(124, 124, 124, 0.2)'],
datalabels: {
textAlign: 'center',
formatter: v => v < 5 ? '' : v
}
}
]
},
options: {
responsive: false,
plugins: {
legend: {
display: false
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#2"></script>
<canvas id="myChart" height="300"></canvas>
Need help with chart js
ACTUALLY, I'M USING VUE-CHARTJS BUT IT'S JUST A WRAPPER
in the line chart on the left side, the number is increasing by 5(0, 5, 10, 15, etc) I want it to increase by 10 and also decrease the height of the chart so the aspect ratio is something like 16/9
also is it possible to make the left number say 5k+, 10k+, 15k+ instead of just 5, 10, 15
here's my code for the chart
<script>
import { Line } from 'vue-chartjs'
export default {
extends: Line,
data: () => ({
chartdata: {
labels: ['January', 'February', 'March', 'April', 'May','Jun'],
datasets: [
{
data: [12, 20, 27, 22, 14, 10],
borderColor: "#135193",
pointBackgroundColor: "#135193",
pointBorderColor: "#135193",
backgroundColor: 'rgba(255, 255, 255, 0)'
},
{
data: [3, 12, 17, 20, 30, 40],
borderColor: "#FF8811",
pointBackgroundColor: "#FF8811",
pointBorderColor: "#FF8811",
backgroundColor: 'rgba(255, 255, 255, 0)'
}
]
},
options: {
responsive: true,
legend: {
display: false
}
}
}),
mounted () {
this.renderChart(this.chartdata, this.options)
}
}
</script>
Yes, you can just use CSS to set the dimensions of the canvas and set maintainAspectRatio to false in the options, for the ticks you can use the tick callback:
const labels = ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"];
const options = {
type: 'line',
data: {
labels,
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'red',
backgroundColor: 'pink'
}]
},
options: {
maintainAspectRatio: false,
scales: {
yAxes: [{
ticks: {
callback: (val) => (`${val}K`)
}
}]
}
}
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
canvas {
max-height: 180px;
max-width: 320px;
}
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script>
</body>
Okay it turns out its as simple as wrapping the chart with a container and set height of that container as needed
I have a bar chart in vue-charts where when clicked I want to display the background data in a table. This is the render
startPie: function(canvas, type){
let chart = new Chart(canvas, {
type: type,
data: {
labels: this.labels,
datasets: this.chart_data
},
options: {
responsive: true,
animation:{ animateScale:true },
title: { display: false },
legend: { display: false },
scales: {
yAxes: [{
gridLines: {
color: "#989898"
},
ticks: {
fontColor: "#989898",
fontSize: 16,
beginAtZero: true,
callback: function(value) {
let ranges = [
{ divider: 1e6, suffix: 'M' },
{ divider: 1e3, suffix: 'k' }
];
function formatNumber(n) {
for (let i = 0; i < ranges.length; i++) {
if (n >= ranges[i].divider) {
return (n / ranges[i].divider).toString() + ranges[i].suffix;
}
}
return n;
}
return '$' + formatNumber(value);
}
}
}],
xAxes: [{
ticks: {
fontColor: "#989898",
fontSize: 12
}
}]
},
plugins: {
datalabels: {
anchor: 'center',
font: {
size: 16,
weight: 'bold'
},
formatter: function(value, context) {
return '$' + Number(value).toLocaleString();
},
color: 'white'
}
},
'onClick':(evt, item) => {
console.log('CLICK', item[0]);
}
}
})
}
In the onClick Event in the console I can see the index
CLICK ChartElement {_chart: Chart, _datasetIndex: 0, _index: 4,
hidden: false, _xScale: ChartElement, …}
I can't access it though without an error. I have tried
item[0]._index, item[0]['_index'], item[0]['ChartElement']._index, item[0]['ChartElement']['_index']
Any help is appreciated.
Unfortunately, the onClick event handler is poorly documented. You could try to define the data in a separate variable outside of the chart configuration.
const data = [55, 68, 82, 48, 75, 45, 67];
Then, you can define the onClick event handler as follows:
options: {
...
onClick: (event, item) => {
const idx = chart.getElementAtEvent(event)[0]._index;
console.log(data[idx]);
}
}
const labels = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"];
const data = [55, 68, 82, 48, 75, 45, 67];
let chart = new Chart(document.getElementById('myChart'), {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: "My First Dataset",
data: data,
backgroundColor: ["rgba(255, 99, 132, 0.2)", "rgba(255, 159, 64, 0.2)", "rgba(255, 205, 86, 0.2)", "rgba(75, 192, 192, 0.2)", "rgba(54, 162, 235, 0.2)", "rgba(153, 102, 255, 0.2)", "rgba(201, 203, 207, 0.2)"],
borderColor: ["rgb(255, 99, 132)", "rgb(255, 159, 64)", "rgb(255, 205, 86)", "rgb(75, 192, 192)", "rgb(54, 162, 235)", "rgb(153, 102, 255)", "rgb(201, 203, 207)"],
borderWidth: 1
}]
},
options: {
responsive: true,
title: {
display: false
},
legend: {
display: false
},
scales: {
yAxes: [{
gridLines: {
color: "#989898"
},
ticks: {
fontColor: "#989898",
fontSize: 16,
beginAtZero: true
}
}]
},
plugins: {
datalabels: {
anchor: 'center',
font: {
size: 16,
weight: 'bold'
},
formatter: function(value, context) {
return '$' + Number(value).toLocaleString();
},
color: 'white'
}
},
onClick: (evt, item) => {
const idx = chart.getElementAtEvent(event)[0]._index;
console.log(data[idx]);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.js"></script>
<canvas id="myChart" height="80"></canvas>