How to add a toggle inside a title of the barchart js - javascript

I have this barchart created in the ChartJS last version.
I want to add a toggle button inside the barchart title, as shown in this picture: https://i.stack.imgur.com/1KMyB.png
This is my barchart code:
var ctx = document.getElementById("myBarChart");
var myBarChart = new Chart(ctx, {
type: 'bar',
data: {
labels: [],
datasets: [{
label: "Valor",
backgroundColor: "rgba(2,117,216,1)",
borderColor: "rgba(2,117,216,1)",
data: [],
}],
},
options: {
plugins: {
datalabels: {
anchor: 'end',
align: 'top',
formatter: function (value, context) {
if (value != 0) {
return new Date(value * 1000).toISOString().substr(11, 8);
} else {
value = " "
return value;
}
},
font: {
weight: 'bold'
}
}
},
responsive: true,
tooltips: {
/* intersect: false, */
callbacks: {
title: function (tooltipItem, data) {
return data['labels'][tooltipItem[0]['index']];
},
label: function (tooltipItem, data) {
return new Date(parseInt(data['datasets'][0]['data'][tooltipItem[
'index']]) * 1000).toISOString().substr(11,
8);
},
},
},
scales: {
xAxes: [{
time: {
unit: 'month'
},
gridLines: {
display: false
},
}],
yAxes: [{
ticks: {
min: 0,
suggestedMax: 36000,
stepSize: 3600,
beginAtZero: true,
},
}],
},
}
});
Is it something possible to do?
If someone know how to do this in the last version of the chartjs, please help me.                                                                  
                                               

You can make use of the core plugin API to write a custom plugin that does it. The better and easyer option to to not use the title of chart.js and put a div above your chart and put your title and the toggle in that div with HTML

Related

chart js 3.9.1 - barchart - margin left

how do i reduce the space between the bar and the y scale? I tried with padding but it doesn't work
Thanks
This is my configuration,I upload the data at runtime and update the graph
Chart.register(ChartDataLabels);
var options = {
tooltips: {
enabled: false
},
plugins:
{
datalabels:
{
color: 'white'
},
legend: {
position: 'top', labels:
{
font: {size: 10},
usePointStyle: true
}
}
},
scales:
{
x: {
barPercentage: 6.5,
categoryPercentage: 0.1
},
y: {
barPercentage: 1,
categoryPercentage: 1,
beginAtZero: true,
grace: '3%',
ticks: {
beginAtZero: true
}
}
}
};
var barChart = new Chart(document.getElementById("chart3"), {
type: 'bar',
data:
{
labels: [""]
},
options:options
});
for (i = 0; i < parsed[0].length; i++)
{
barChart.data.datasets.push({ label: parsed[0][i].label, backgroundColor: parsed[0][i].backgroundColor, data: ["" + parsed[0][i].data + ""], pointStyle:'circle' });
}
barChart.update();
The issue sounds being related to categoryPercentage and barPercentage options that you are set in the axis but this is not the right place.
Move those options in the chart.options and it should work.
Try using categoryPercentage: 1.
var options = {
categoryPercentage: 1,
plugins:
{
datalabels:
{
color: 'white'
},
legend: {
position: 'top', labels:
{
font: {size: 10},
usePointStyle: true
}
}
tooltip: {
enabled: false
},
},
scales:
{
y: {
beginAtZero: true,
grace: '3%',
}
}
};

Style individual points from one dataset in Chart.js

I am trying to create a timeline using Chart.js.
My Goal is to have a single row that shows various icons/events that happened in a game.
By using a linechart and removing the lines, leaving only the points, you can place markers on the timeline.
You can display these points as custom images by assigning an image variable to the pointStyle attribute of the dataset.
With a single image this works perfectly fine, as you can see in the following snippet.
//Create the image
const img = new Image(20,20);
img.src = "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Skull_Icon_%28Noun_Project%29.svg/1200px-Skull_Icon_%28Noun_Project%29.svg.png";
var ctx = document.getElementById('chart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [
{
label: "Deaths",
data: [{x:"00:01:23", y: 0},{x:"00:03:41", y: 0},{x:"00:04:29", y: 0},{x:"00:05:35", y: 0},{x:"00:06:27", y: 0},{x:"00:07:07", y: 0},{x:"00:08:48", y: 0},{x:"00:09:31", y: 0}],
//Assign the image in the point Style attribute
pointStyle:img,
showLine: false,
fill: false,
tooltip: "Player Died",
borderColor: "#000000",
backgroundColor: "#000000"
},
]},
//The Rest is just styling
options: {
interaction:{
mode:'nearest'
},
tooltips:{
custom: function(tooltip){
if(!tooltip)return;
tooltip.displayColors = false;
},
callbacks:{
title: function(tooltipItem, data) {
return data.datasets[tooltipItem[0].datasetIndex]['tooltip'];
},
label: function(tooltipItem, data) {
return tooltipItem.xLabel;
}
}
},
legend: {
display: true
},
scales: {
xAxes: [{
type: 'time',
time: {
parser: 'hh:mm:ss',
tooltipFormat: 'HH:mm:ss',
displayFormats: {
second: "HH:mm:ss"
},
unitStepSize: 30
},
ticks:{
fontColor: "white"
}
}],
yAxes: [{
ticks: {
display: false,
},
gridLines: {
display: false
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.bundle.min.js"></script>
<canvas id="chart" height= "50px" style="background-color: rgb(200, 200, 200);"></canvas>
As you can see i am creating an Image(), pointing it to the source and assigning it as the pointStyle attribute of the dataset.
But with this method i need to create a new Dataset whenever i want to display another image.
For my purpose i need to be able to dynamically assign different images for every point.
That is why i looked into scriptables in Chart.js. On the documentation it is stated that you can use custom functions to return an image/styling for pointStyles.
https://www.chartjs.org/docs/latest/general/options.html
In the following snippet you can see my current code.
I moved the creation of the image to a custom function in the point Style attribute of the dataset. With this i will be able to select from more images later.
But for now i can not make it work with one image. So how can i make the function return an image, so that the styling works? With this i will later be able to select from multiple images. Or is there maybe another solution i did not come up with?
Thank you very much for your help.
var ctx = document.getElementById('chart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [
{
label: "Deaths",
data: [{x:"00:01:23", y: 0},{x:"00:03:41", y: 0},{x:"00:04:29", y: 0},{x:"00:05:35", y: 0},{x:"00:06:27", y: 0},{x:"00:07:07", y: 0},{x:"00:08:48", y: 0},{x:"00:09:31", y: 0}],
//Try to create the image in a custom function
pointStyle: function(context){
var img = new Image(20,20);
img.src = "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Skull_Icon_%28Noun_Project%29.svg/1200px-Skull_Icon_%28Noun_Project%29.svg.png";
return img;
},
showLine: false,
fill: false,
tooltip: "Player Died",
borderColor: "#000000",
backgroundColor: "#000000"
},
]},
options: {
interaction:{
mode:'nearest'
},
tooltips:{
custom: function(tooltip){
if(!tooltip)return;
tooltip.displayColors = false;
},
callbacks:{
title: function(tooltipItem, data) {
return data.datasets[tooltipItem[0].datasetIndex]['tooltip'];
},
label: function(tooltipItem, data) {
return tooltipItem.xLabel;
}
}
},
legend: {
display: true
},
scales: {
xAxes: [{
type: 'time',
time: {
parser: 'hh:mm:ss',
tooltipFormat: 'HH:mm:ss',
displayFormats: {
second: "HH:mm:ss"
},
unitStepSize: 30
},
ticks:{
fontColor: "white"
}
}],
yAxes: [{
ticks: {
display: false,
},
gridLines: {
display: false
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.bundle.min.js"></script>
<canvas id="chart" height= "50px" style="background-color: rgb(200, 200, 200);"></canvas>
You can add different images via an array.
//Create the image
const img = new Image(20, 20);
img.src = "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Skull_Icon_%28Noun_Project%29.svg/1200px-Skull_Icon_%28Noun_Project%29.svg.png";
const img2 = new Image(20, 20);
img2.src = "https://pngimg.com/uploads/pacman/pacman_PNG21.png";
const img3 = new Image(20, 20);
img3.src = "https://pngimg.com/uploads/pacman/pacman_PNG70.png"
var ctx = document.getElementById('chart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: "Deaths",
data: [{
x: "00:01:23",
y: 0
}, {
x: "00:03:41",
y: 0
}, {
x: "00:04:29",
y: 0
}, {
x: "00:05:35",
y: 0
}, {
x: "00:06:27",
y: 0
}, {
x: "00:07:07",
y: 0
}, {
x: "00:08:48",
y: 0
}, {
x: "00:09:31",
y: 0
}],
//Assign the image in the point Style attribute
pointStyle: [img2, img, img3],
showLine: false,
fill: false,
tooltip: "Player Died",
borderColor: "#000000",
backgroundColor: "#000000"
}, ]
},
//The Rest is just styling
options: {
interaction: {
mode: 'nearest'
},
tooltips: {
custom: function(tooltip) {
if (!tooltip) return;
tooltip.displayColors = false;
},
callbacks: {
title: function(tooltipItem, data) {
return data.datasets[tooltipItem[0].datasetIndex]['tooltip'];
},
label: function(tooltipItem, data) {
return tooltipItem.xLabel;
}
}
},
legend: {
display: true
},
scales: {
xAxes: [{
type: 'time',
time: {
parser: 'hh:mm:ss',
tooltipFormat: 'HH:mm:ss',
displayFormats: {
second: "HH:mm:ss"
},
unitStepSize: 30
},
ticks: {
fontColor: "white"
}
}],
yAxes: [{
ticks: {
display: false,
},
gridLines: {
display: false
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.min.js"></script>
<canvas id="chart" height="50px" style="background-color: rgb(200, 200, 200);"></canvas>
How you get the images to the array is up to you.
You can update it with something like this
function addimage(img) {
myChart.data.datasets[0].pointStyle.push(img);
myChart.update();
};
addimage(img2)
Of course you will want to add your images in some other dynamic way I’m sure but this should help.

Javascript Canvas labels too long

When I use small version numbers (the label), my canvas is shown as it should:
But when my labels get too long it starts to look very unreadable, and I don't know how to avoid this?:
Can I change my options to solve this, if yes, how?
Here is my javascript function, and nameArray is the array with version numbers, and I have to shorten these somehow.
function renderBarChart(nameArray, passArray, failArray, divId, title) {
var ctx = document.getElementById(divId).getContext('2d');
var newChart = new Chart(ctx, {
type: 'bar',
data: {
labels: nameArray,
datasets: [{
label: 'Passed',
data: passArray,
backgroundColor: 'rgb(150,238,144)'
},
{
label: 'Failed',
data: failArray,
backgroundColor: 'rgb(204,0,0)'
}
]
},
options: {
title: {
display: true,
text: title
},
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'nearest',
intersect: true
},
responsive: false,
maintainAspectRatio: false,
scales: {
xAxes: [{
stacked: true,
ticks: {
stepSize: 1,
min: 0,
autoSkip: false
}
}],
yAxes: [{
stacked: true,
ticks: {
maxTicksLimit: 5,
min: 0
}
}]
}
}
});
}
EDIT 1
Right now I'm trying to do something like this, but I can't make it work.
Inspiration form: How to shorten Chart.js label
function renderBarChart(nameArray, passArray, failArray, divId, title) {
var ctx = document.getElementById(divId).getContext('2d');
var newChart = new Chart(ctx, {
type: 'bar',
data: {
labels: nameArray,
datasets: [{
label: 'Passed',
data: passArray,
backgroundColor: 'rgb(150,238,144)'
},
{
label: 'Failed',
data: failArray,
backgroundColor: 'rgb(204,0,0)'
}
]
},
options: {
title: {
display: true,
text: title
},
tooltips: {
enabled: true,
mode: 'label',
callbacks: {
title: function(tooltipItems, data) {
var idx = tooltipItems[0].index;
return 'Title:' + data.labels[idx]; //do something with title
},
label: function(tooltipItems, data) {
//var idx = tooltipItems.index;
//return data.labels[idx] + ' €';
return tooltipItems.xLabel + ' €';
}
}
},
hover: {
mode: 'nearest',
intersect: true
},
responsive: false,
maintainAspectRatio: false,
scales: {
xAxes: [{
stacked: true,
ticks: {
stepSize: 1,
min: 0,
autoSkip: false,
callback: function(value) {
if (value.length > 4) {
return value.substr(0, 4) + '...'; //truncate
} else {
return value
}
},
}
}],
yAxes: [{
stacked: true,
ticks: {
maxTicksLimit: 5,
min: 0
}
}]
}
}
});
}

ChartJS How to set color to just one bar

I have this barChart and I'm with difficult to set a color by script to just one bar of the index.
Bellow is my chartbar code:
var ctx = document.getElementById("myBarChart");
var myBarChart = new Chart(ctx, {
type: 'bar',
data: {
labels: [],
datasets: [{
label: "Valor",
backgroundColor: "rgba(2,117,216,1)",
borderColor: "rgba(2,117,216,1)",
data: [],
}],
},
options: {
plugins: {
datalabels: {
anchor: 'end',
align: 'top',
formatter: function (value, context) {
if (value != 0) {
return new Date(value * 1000).toISOString().substr(11, 8);
} else {
value = " "
return value;
}
},
font: {
weight: 'bold'
}
}
},
responsive: true,
tooltips: {
/* intersect: false, */
callbacks: {
title: function (tooltipItem, data) {
return data['labels'][tooltipItem[0]['index']];
},
label: function (tooltipItem, data) {
return new Date(parseInt(data['datasets'][0]['data'][tooltipItem[
'index']]) * 1000).toISOString().substr(11,
8);
},
},
},
scales: {
xAxes: [{
time: {
unit: 'month'
},
gridLines: {
display: false
},
}],
yAxes: [{
ticks: {
min: 0,
suggestedMax: 36000,
stepSize: 3600,
beginAtZero: true,
},
}],
},
}
});
I have tried this:
myBarChart.data.datasets[0].backgroundColor[0]
But it doesnt work.
If someone know how to do this in the last version of the chartjs, please help me.
You can provide an array to the backgroundColor property. In this array you can fill it with the default color except for the index where you want the bar to be a different collor

Chart.JS Can not read property '_meta' of Undefined

I am attempting to build a basic bar chart, but I am getting the error in the title. I have used alert() to verify that the array I want to populate the chart with holds data, but something is still not fishing out properly with the syntax. Can someone examine and let me know what I need to do better in order to make the chart produce?
var ctx = document.getElementById('cvtree').getContext('2d');
var chart = new Chart(ctx, {
type: 'bar',
data: {
labels: yoylabels,
datasets: [{
label: 'Pay By Person',
backgroundColor: 'rgba(0, 129, 214, 0.8)',
data: numericdollarvals
}]
},
options: {
},
legend: {
display: false,
position: 'top',
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
callback: function (value, index, values) {
if (parseInt(value) >= 1000) {
return '$' + value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
} else {
return '$' + value;
}
}
}
}]
}
});
You are unexpectedly closing off the options property, before setting all the options.
Here is the correct syntax :
var ctx = document.getElementById('cvtree').getContext('2d');
var chart = new Chart(ctx, {
type: 'bar',
data: {
labels: yoylabels,
datasets: [{
label: 'Pay By Person',
backgroundColor: 'rgba(0, 129, 214, 0.8)',
data: numericdollarvals
}]
},
options: {
legend: {
display: false,
position: 'top',
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
callback: function(value, index, values) {
if (parseInt(value) >= 1000) {
return '$' + value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
} else {
return '$' + value;
}
}
}
}]
}
}
});

Categories

Resources