Why labels on x-asis does not shows well? - chart.js

Here is my div with canvas for line chart:
<div
x-data="{
lineChartLabels: #entangle('lineChartLabels'),
lineChartData: #entangle('lineChartData'),
init() {
const labels = `${this.lineChartLabels}`;
const data = {
labels: labels,
datasets: [{
backgroundColor: 'lightblue',
data: this.lineChartData,
fill: true,
label: `{{__('site.report.values')}}`,
}]
};
const config = {
type: 'line',
data: data,
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
ticks: {
callback: function (value) {
const date = new Date(Number(value) * 1000);
return date.toISOString().substring(11,23);
}
}
}
},
plugins: {
tooltip: {
callbacks: {
label: function (context) {
const date = new Date(Number(context.formattedValue) * 1000);
return date.toISOString().substring(11,23);
}
}
}
}
}
};
const myChart = new Chart(
this.$refs.canvas,
config
);
Livewire.on('updateTheChart', () => {
myChart.destroy();
myChart.data.datasets[0].data = this.lineChartData;
myChart.data.labels = this.lineChartLabels;
myChart.update();
})
}
}">
<canvas id="myChart" x-ref="canvas" style="height: 33vh;width: 50vw;"></canvas>
</div>
And here is an example of values(which represent seconds):
[49.66,47.26,46.88,49.81]
and for x axis which represents dates:
["04-Feb-17","06-May-17","28-Oct-17","20-Dec-17"]
But when it renders it shows like this:
Can somebody tell me why chartjs does not show x-asis in the proper way and how to fix it?

The problem is this line const labels = `${this.lineChartLabels}`; you are creating a script, what you need ist the array, so with other words: const labels = this.lineChartLabels; remove the string interpolation.
Disclaimer: I'm guessing abit, because I'm not acquainted with laravel-livewire and alpine.js, but that line of code looks like the culprit to me.
Here the two different Version, side by side:
const labels = ["04-Feb-17","06-May-17","28-Oct-17","20-Dec-17"];
const data = {
labels: labels,
datasets: [{
backgroundColor: 'lightblue',
data: [49.66,47.26,46.88,49.81],
fill: true,
label: `Correct Version`,
}]
};
const config = {
type: 'line',
data: data,
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
ticks: {
callback: function (value) {
const date = new Date(Number(value) * 1000);
return date.toISOString().substring(11,23);
}
}
}
},
plugins: {
tooltip: {
callbacks: {
label: function (context) {
const date = new Date(Number(context.formattedValue) * 1000);
return date.toISOString().substring(11,23);
}
}
}
}
}
};
new Chart(
document.getElementById('chart'),
config
);
config.data.labels = `${["04-Feb-17","06-May-17","28-Oct-17","20-Dec-17"]}`;
config.data.datasets[0].label = `Incorrect Version`;
let chart2 = new Chart(
document.getElementById('chart2'),
config
);
<script src="//cdn.jsdelivr.net/npm/chart.js"></script>
<div class="chart" style="float:left;height:184px; width:300px;font-family: Arial">
<canvas id="chart" ></canvas>
</div>
<div class="chart" style="float:left;height:184px; width:300px;font-family: Arial">
<canvas id="chart2" ></canvas>
</div>

Related

Chart.min.js - sometimes the chart is displayed and sometimes not

hello I have the following problem I use the plugin Chart.js to display statistics now I have the following problem sometimes the chart is displayed and sometimes not see screenshot
I have asked in a Discord Chat but that did not help, i hope i can get help here
Chart.js Version:2.1.4
The Code:
function LoadProviderChart() {
$(document).ready(function() {
var providercount = JSON.parse(window.localStorage.getItem('providercount_' + window.location.pathname.split('/')[4]));
console.log(providercount);
providercount = Object.keys(providercount).map(function (key) {
return [key, providercount[key]];
})
providercount.sort(function (a, b) {
return b[1].count - a[1].count;
})
var cutProviderCount = providercount.slice(0, 6);
if(window.ProviderChart != null) {
window.ProviderChart.destroy();
console.log("ProviderChart destroyed");
}
Chart.defaults.global.defaultFontFamily = 'Rubik';
Chart.defaults.global.defaultFontColor = '#fff';
var ctxB = document.getElementById("barChart").getContext('2d');
var config = {
type: 'bar',
data: {
labels: cutProviderCount.map(function(x) { return x[0] }),
datasets: [{
label: 'Games of Providers',
data: cutProviderCount.map(function(x) { return x[1].count }),
backgroundColor: "" + getComputedStyle(document.body).getPropertyValue('--highlight_color').toString().replace(' ', '') + "",
}],
},
options: {
scales: {
yAxes: [{
gridLines:{
display: false,
},
ticks: {
beginAtZero: true
}
}],
xAxes: [{
gridLines:{
display:false,
},
}]
}
}
}
window.ProviderChart = new Chart(ctxB, config);
});
}

Horizontal floating bars with a time y-axis in Chart.js

I'm trying to adapt https://www.chartjs.org/docs/latest/samples/bar/floating.html to create a kind of timeline chart, where the horizontal axis (the range data) are timestamps. Unfortunately I can't seem to get the data to display, and don't see any error messages, etc.
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/moment#^2"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js#^3"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment#^1"></script>
</head>
<body>
<div>
<canvas id="myChart"></canvas>
</div>
</body>
<script>
//const labels = ["a","b","c","d","fff","g","h"]
const labels = ["a","b"]
const data = {
labels: labels,
datasets: [
{
label: 'Dataset 1',
data: [[moment("2021-11-23T00:24:14Z"),moment("2021-11-23T00:34:03Z")],
[moment("2021-11-23T00:24:14Z"),moment("2021-11-23T00:26:35Z")]]
// This works fine (without 'yAxes' below):
//data: labels.map(() => {
//return [Math.random(), Math.random()];
//}),
//backgroundColor: Utils.CHART_COLORS.red,
},
]
};
const config = {
type: 'bar',
data: data,
options: {
yAxes: [{
type: 'time',
}],
indexAxis: 'y',
responsive: true,
plugins: {
legend: {
position: 'top',
},
title: {
display: true,
text: 'Chart.js Floating Bar Chart'
}
}
}
};
var ctx = document.getElementById("myChart").getContext("2d");
new Chart(ctx, config);
</script>
</html>
EDIT: JSFiddle: https://jsfiddle.net/r5ypuvks/
Mmm it seems my issues are:
not using proper axis format for chart.js 3
need to scale the graph myself
need to refer to horizontal axis as x
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/moment#^2"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js#^3"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment#^1"></script>
</head>
<body>
<div>
<canvas id="myChart"></canvas>
</div>
</body>
<script>
//const labels = ["a","b","c","d","fff","g","h"]
const labels = ["a","b"]
const data = {
labels: labels,
datasets: [
{
label: 'Dataset 1',
data: [[("2021-11-23T00:24:14Z"),("2021-11-23T00:34:03Z")],
[("2021-11-23T00:25:14Z"),("2021-11-23T00:26:35Z")]]
// This works fine (without 'yAxes' below):
//data: labels.map(() => {
//return [Math.random(), Math.random()];
//}),
//backgroundColor: Utils.CHART_COLORS.red,
},
]
};
const config = {
type: 'bar',
data: data,
options: {
scales: {
x: {
min: ("2021-11-23T00:20:14Z"),
max: ("2021-11-23T00:44:14Z") ,
type: 'time',
},
},
indexAxis: 'y',
responsive: true,
plugins: {
legend: {
position: 'top',
},
title: {
display: true,
text: 'Chart.js Floating Bar Chart'
}
}
}
};
var ctx = document.getElementById("myChart").getContext("2d");
new Chart(ctx, config);
</script>
</html>

Is it possible to draw a bar and arrow/pointer on the right side of a chart?

I currently have this chart.
I'm attempting to create something like this.
The bar on the side is static, but the section "heights" need to be programmable when the page loads. I attempted encoding in an SVG but I wasn't able to get it to stick to the chart.
I've got no clue how to make the final (current value) node to appear as an arrow pointing to the bar (or alternatively, as just a horizontal bar across the vertical one).
I made a sample codepen to simulate the dynamic chart I currently have.
(Or, per StackOverflow's requirements, the JS code used: )
var randoms = [...Array(11)].map(e=>~~(Math.random()*11));
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: randoms,
datasets: [{
label: 'value',
data: randoms
}]
},
options: {
scales: {
y: {
grace: 10,
}
}
}
});
function populate(){
let temp = ~~(Math.random()*11);
myChart.data.datasets[0].data.shift();
myChart.data.datasets[0].data.push(temp);
myChart.update();
}
setInterval(populate, 10000);
Any general pointers are also appreciated - I'm very new to all of this.
You can write a custom plugin for this, I added padding on the right to give space for the arrow to be drawn. You can play with the multiplyer values to make the arrow bigger/smaller
Example:
var randoms = [...Array(11)].map(e => ~~(Math.random() * 11));
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: randoms,
datasets: [{
label: 'value',
data: randoms,
borderColor: 'red',
backgroundColor: 'red'
}]
},
options: {
layout: {
padding: {
right: 25
}
},
scales: {
y: {
grace: 10
}
}
},
plugins: [{
id: 'arrow',
afterDraw: (chart, args, opts) => {
const {
ctx
} = chart;
chart._metasets.forEach((meta) => {
let point = meta.data[meta.data.length - 1];
ctx.save();
ctx.fillStyle = point.options.backgroundColor;
ctx.moveTo(point.x, (point.y - point.y * 0.035));
ctx.lineTo(point.x, (point.y + point.y * 0.035));
ctx.lineTo((point.x + point.x * 0.025), point.y)
ctx.fill();
ctx.restore();
})
}
}]
});
function populate() {
let temp = ~~(Math.random() * 11);
myChart.data.datasets[0].data.shift();
myChart.data.datasets[0].data.push(temp);
myChart.update();
}
//setInterval(populate, 10000);
<script src="https://npmcdn.com/chart.js#latest/dist/chart.min.js"></script>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"></canvas>
</div>

Is it possible to create context menu with chart.js?

I wanted to create a context menu on my line graph. When the user hovers across a point, they can right click and will see a context menu so that they can trigger more action.
Is this possible with chart.js?
Thanks,
Derek
AFAIK there is no native support for context menu from Chart.js, but you can create it using HTML and handle it.
This is an example:
var timestamp = [],
speed = [10, 100, 20, 30, 40, 100, 40, 60];
for (var k = speed.length; k--; k>0) {
timestamp.push(new Date().getTime()-60*60*1000*k);
}
var canvas = document.getElementById('chart');
var BB = canvas.getBoundingClientRect(),
offsetX = BB.left,
offsetY = BB.top;
var ctx = canvas.getContext("2d");
var data = {
labels: timestamp,
datasets: [{
data: speed,
label: "speed",
backgroundColor: ['rgba(0, 9, 132, 0.2)'],
borderColor: ['rgba(0, 0, 192, 1)'],
borderWidth: 1,
}
]
};
var options = {
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
}
}],
xAxes: [{
type: 'time',
}]
}
};
var chart = new Chart(ctx, {
type: 'line',
data: data,
options: options
});
var $menu = $('#contextMenu');
canvas.addEventListener('contextmenu', handleContextMenu, false);
canvas.addEventListener('mousedown', handleMouseDown, false);
function handleContextMenu(e){
e.preventDefault();
e.stopPropagation();
var x = parseInt(e.clientX-offsetX);
var y = parseInt(e.clientY-offsetY);
$menu.css({left:x,top:y});
$menu.show();
return(false);
}
function handleMouseDown(e){
$menu.hide();
}
menu = function(n){
console.log("select menu "+n);
$menu.hide();
}
#chart {
width: 100%;
height: 100%;
}
#contextMenu{
position:absolute;
border:1px solid red;
background:white;
list-style:none;
padding:3px;
}
.menu-item:hover {
background: #dddddd;
text-decoration: underline;
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id=canvasContainer>
<canvas id="chart"></canvas>
<ul id="contextMenu" style="display:none;">
<li class="menu-item" onclick="menu(1)">Menu 1</li>
<li class="menu-item" onclick="menu(2)">Menu 2</li>
</ul>
</div>
For anyone looking for this, #beaver's answer does not have access to the clicked item (data point), you can save the state in onHover and use it in contextmenu.
options: {
events: ['click', 'mousemove'],
onHover: function(e, fields){
const lx = e.layerX;
const bars = fields.filter(({_view: {x,width}}) => (x - width/2) <= lx && lx <= (x + width/2));
const data = bars.map(({_index, _datasetIndex}) => this.data.datasets[_datasetIndex].data[_index]);
this.hoveredItem = {bars, data, fields};
},
},
plugins: [
{
afterInit: (chart) =>
{
var menu = document.getElementById("contextMenu");
chart.canvas.addEventListener('contextmenu', handleContextMenu, false);
chart.canvas.addEventListener('mousedown', handleMouseDown, false);
function handleContextMenu(e){
e.preventDefault();
e.stopPropagation();
menu.style.left = e.clientX + "px";
menu.style.top = e.clientY + "px";
menu.style.display = "block";
console.log(chart.hoveredItem);
return(false);
}
function handleMouseDown(e){
menu.style.display = "none";
}
}
}
],
https://codepen.io/elizzk/pen/xxZjQvJ

How to remove square label from tooltip and make its information in one line?

How can I remove this square from tooltip?
I would prefer if I could manage to just have it one line like this: February - 2
var data = {
labels: ['January', 'February', 'March'],
datasets: [
{
data: [1,2,3]
}
]
};
var myLineChart = new Chart(document.getElementById('chart'), {
type: 'line',
data: data,
options: {
legend: {
display: false
}
}
});
Add this in your options object
tooltips: {
displayColors: false
}
Update for version 3 or greater (from #hanumanDev below):
Remove 's' from tooltips
tooltip: {
displayColors: false
}
here you go:
jsfiddle: http://jsfiddle.net/1v9fy5mz/
code:
html
<canvas id="canvas"></canvas>
js:
var ctx = document.getElementById("canvas").getContext("2d");
var data = {
labels: ['January', 'February', 'March'],
datasets: [{
data: [1, 2, 3]
}]
};
var myLineChart = new Chart(ctx, {
type: 'line',
data: data,
options: {
showAllTooltips: true,
tooltips: {
custom: function(tooltip) {
if (!tooltip) return;
// disable displaying the color box;
tooltip.displayColors = false;
},
callbacks: {
// use label callback to return the desired label
label: function(tooltipItem, data) {
return tooltipItem.xLabel + " :" + tooltipItem.yLabel;
},
// remove title
title: function(tooltipItem, data) {
return;
}
}
}
}
});
tooltips: {
displayColors: false,
callbacks: {
// use label callback to return the desired label
label: function(tooltipItem, data) {
return tooltipItem.xLabel + " :" + tooltipItem.yLabel;
},
// remove title
title: function(tooltipItem, data) {
return;
}
}
}
In version 3.8.0 of the chart.js plugin the tooltip config needs to go in the plugins config object, like this:
options: {
plugins: {
tooltip: {
displayColors: false
}
}
}