VueJS and dynamic reload ChartJS when screen resize - chart.js

I'm trying to figure out, how I can reload my ChartJS components whenever the screensize is changed as it's messing up the responsiveness at the moment. My goal is to either reload them after resize, or remove them while resizing and loading again after resize.
This is my code so far for the graph component, for some reason it's ignoring the timer, but maybe the ready() isn't just called when the component is loaded?
export default {
props: {
type: {
type: String,
required: true
}
},
data() {
return {
data: {
labels: ['2014', '2015', '2016', '2016'],
datasets: [
{
label: "Administration",
backgroundColor: "rgba(255, 219, 77, 0.5)",
borderColor: "rgba(255, 219, 77, 1)",
borderWidth: 0,
hoverBackgroundColor: "rgba(255, 219, 77, 0.8)",
hoverBorderColor: "rgba(255, 219, 77, 1)",
data: [65, 59, 80, 81],
},
{
label: "Teaching",
backgroundColor: "rgba(255, 166, 77, 0.5)",
borderColor: "rgba(255, 166, 77, 1)",
borderWidth: 0,
hoverBackgroundColor: "rgba(255, 166, 77, 0.8)",
hoverBorderColor: "rgba(255, 166, 77, 1)",
data: [65, 59, 80, 81],
},
{
label: "Exam & Supervision",
backgroundColor: "rgba(102, 153, 204, 0.5)",
borderColor: "rgba(102, 153, 204, 1)",
borderWidth: 0,
hoverBackgroundColor: "rgba(102, 153, 204, 0.8)",
hoverBorderColor: "rgba(102, 153, 204, 1)",
data: [65, 59, 80, 81],
}
]
},
timoutHandle: null
}
},
ready() {
window.addEventListener('resize', this.reload);
this.loadChart();
},
methods: {
loadChart() {
console.log('loading..');
new Chart(
this.$el.getContext('2d'),
{
type: this.type,
data: this.data,
options: {
legend: {
position: 'bottom'
}
}
}
);
},
reload() {
window.clearTimeout(this.timeoutHandle);
this.timeoutHandle = window.setTimeout(
this.loadChart(),
3);
}
}
}

Have you consider using vue-charts? It's google-chart wrapper for vue and it exports draw method and resizing on window size change is quite easy:
<template>
<vue-chart
:chart-type="chartType"
:columns="columns"
:chart-events="chartEvents"
:rows="rowData"
:options="options"
v-ref:thisherechart
></vue-chart>
</template>
ready: function() {
var self = this;
jQuery(window).resize(function () {
self.$refs.thisherechart.drawChart();
})
},
Same jQuery may help You with your problem.

I fixed this part of the problem, look here for reference: https://github.com/chartjs/Chart.js/issues/2777#issuecomment-226219784

Related

Chart.js How To Show Tooltip on Legend Hover

I am trying to show a tooltip with the graph data (label and y value) when the corresponding legend key is hovered over. I can only find solutions which work for older versions of Chart.js, I am using 3.8.0.
This can be done by defining a options.plugins.legend.onHover function as follows:
legend: {
onHover: (evt, legendItem) => {
const activeElement = {
datasetIndex: 0,
index: legendItem.index
};
chart.tooltip.setActiveElements([activeElement]);
chart.update();
}
}
Please take a look at the runnable code below and see how it works.
const chart = new Chart('chart', {
type: 'doughnut',
data: {
labels: ['One', 'Two', 'Three'],
datasets: [{
data: [4, 5, 3],
backgroundColor: ['rgba(255, 99, 132, 0.2)', 'rgba(255, 159, 64, 0.2)', 'rgba(54, 162, 235, 0.2)'],
borderColor: ['rgb(255, 99, 132)', 'rgb(255, 159, 64)', 'rgb(54, 162, 235)'],
hoverBackgroundColor: ['rgba(255, 99, 132, 0.4)', 'rgba(255, 159, 64, 0.4)', 'rgba(54, 162, 235, 0.4)'],
borderWidth: 1,
hoverBorderWidth: 3
}]
},
options: {
plugins: {
legend: {
onHover: (evt, legendItem) => {
const activeElement = {
datasetIndex: 0,
index: legendItem.index
};
chart.setActiveElements([activeElement]); // to also show thick border
chart.tooltip.setActiveElements([activeElement]);
chart.update();
}
}
}
}
});
canvas {
max-height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.min.js"></script>
<canvas id="chart"></canvas>

Canvas line chart on this graph stretch beyond the assigned lengths

Why does the line chart on this graph stretch beyond the assigned lengths. In this demo I have a line chart where the height automatically grows to 2355 although I am setting the canvas height to 250. How can I control the height of the line chart? Thank you.
JS:
var ctx2 = document.getElementById('lineChart').getContext('2d');
var lineChart = new Chart(ctx2, {
type: "line",
data: {
labels: [500, 600, 700, 750, 800, 850, 900, 950, 999, 050],
datasets: [
{
data: [86, 114, 106, 106, 107, 111, 133, 221, 783, 2478],
label: "Infrastructure",
borderColor: "#3e95cd",
fill: false
},
{
data: [282, 350, 411, 502, 635, 809, 947, 1402, 3700, 5267],
label: "CSI",
borderColor: "#8e5ea2",
fill: false
},
{
data: [168, 170, 178, 190, 203, 276, 408, 547, 675, 734],
label: "DevOps",
borderColor: "#3cba9f",
fill: false
},
{
data: [40, 20, 10, 16, 24, 38, 74, 167, 508, 784],
label: "Enterprise SIEM",
borderColor: "#e8c3b9",
fill: false
},
{
data: [6, 3, 2, 2, 7, 26, 82, 172, 312, 433],
label: "Bug Fix/Feature Request",
borderColor: "#c45850",
fill: false
}
]
},
options: {
title: {
display: true,
text: "Ticket Trends"
}
}
});
add !important attribute
#barChart{
height: 250px !important;
width: 250px !important;
}
https://www.w3schools.com/css/css_important.asp

How to change the position of the tooltip for the Bar type chart in Chart.Js

By default Chart.js will display the tool tip at the top of the bar for the bar type of charts.
I am trying to change the default position of the tooltip from the top to the center of the bar.
Which is some thing similar to as shown in the below image.
Appreciate help on this, Thank you.
You need to define a new tooltip position mode as follows:
Chart.Tooltip.positioners.middle = elements => {
let model = elements[0]._model;
return {
x: model.x,
y: (model.base + model.y) / 2
};
};
Further you have to define tooltips within the chart options as follows:
tooltips: {
position: 'middle', // must match the positioner function name defined above
yAlign: null, // to get rid of the pointer
xAlign: 'center'
}
Please take a look at below runnable code snippet and see how it works:
Chart.Tooltip.positioners.middle = elements => {
let model = elements[0]._model;
return {
x: model.x,
y: (model.base + model.y) / 2
};
};
new Chart(document.getElementById("chart"), {
type: "bar",
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My Dataset",
data: [65, 59, 80, 81, 56, 55, 40],
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: {
tooltips: {
position: 'middle',
yAlign: null,
xAlign: 'center'
},
legend: {
display: false
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<canvas id="chart" height="90"></canvas>
Display the resulting chart in full page mode if the tooltips don't show up in embedded mode.

ChartJS Custom text on certain xAxis and yAxis linesS

See attached screenshot with an example with what I'm trying to do.
Basically I want to be able to add custom text on certain yAxis and xAxis lines.
You can use the Plugin Core API. It offers different hooks that may be used for executing custom code. In below code snippet, I use the afterDraw hook to draw custom text on the canvas.
For positioning your text on x and y, you may use hard coded number of pixels or compute them using the Scale Interface (i.e. function getPixelForValue).
new Chart(document.getElementById('myChart'), {
type: 'bar',
plugins: {
afterDraw: chart => {
var ctx = chart.chart.ctx;
var xAxis = chart.scales['x-axis-0'];
var yAxis = chart.scales['y-axis-0'];
ctx.save();
ctx.font = "18px Arial";
ctx.fillStyle = "red";
var x = (xAxis.getPixelForValue('May') + xAxis.getPixelForValue('June')) / 2;
ctx.fillText('My custom text here', x, yAxis.getPixelForValue(65));
ctx.fillText('Another custom text here', 30, 15);
ctx.restore();
}
},
data: {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: "My First Dataset",
data: [65, 59, 80, 81, 56, 55, 40],
fill: false,
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: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="myChart" height="110"></canvas>

Highlight background on a single hour with chart.js and annotations

I'm using chart.js and chartjs-plugin-annotation to highlight areas on a graph:
The following config generates the result above:
annotation: {
events: ["click"],
annotations: [
{
type: "box",
drawTime: "beforeDatasetsDraw",
xScaleID: 'x-axis-0',
yScaleID: 'y-axis-0',
xMin: "2019-08-09T07:00:00Z",
xMax: "2019-08-09T09:00:00Z",
yMin: 0,
yMax: 7,
borderWidth: 0,
backgroundColor: "rgba(230,97,79,0.3)",
onClick: function (e) {
console.log("Annotation", e.type, this);
}
}
]
}
I want to be able to highlight a single hour, though:
Anyone if this is possible using the annotations plugin?
To be able to reproduce your request i used annotation type line instead of box.
Annotation type line only accepts borderWidth for thickness of the line.
Because the borderWidth needs to match the column size, i got the width of the chart chart.width, and i divided it to the number of columns chart.data.datasets[0].data.length. Of course i used Chart.js Plugin extension hooks for that:
afterInit (Called after chart has been initialized and before the first update.)
resize (Called after the chart as been resized.)
Code:
var ctx = document.getElementById("myChart");
var dataAnnotation = [
{
type: 'line',
mode: 'vertical',
scaleID: 'x-axis-0',
value: "2019-08-09T08:00:00Z",
borderColor: 'rgba(255, 99, 132, 0.2)',
borderWidth: null,
onClick: function (e) {
console.log("Annotation", e.type, this);
}
},
{
type: 'line',
mode: 'vertical',
scaleID: 'x-axis-0',
value: "2019-08-09T11:00:00Z",
borderColor: 'rgba(255, 99, 132, 0.2)',
borderWidth: null,
onClick: function (e) {
console.log("Annotation", e.type, this);
}
}
];
Chart.plugins.register({
resize: function(chart) {
columns = chart.data.datasets[0].data.length;
chartWidth = chart.width - 40;
setBorderWidth = chartWidth / columns;
annotationsData = chart.options.annotation.annotations.map(function(item){
item.borderWidth = setBorderWidth;
return item;
});
chart.options.annotation.annotations = annotationsData;
chart.update();
},
afterInit: function(chart) {
columns = chart.data.datasets[0].data.length;
chartWidth = chart.width - 40;
setBorderWidth = chartWidth / columns;
annotationsData = dataAnnotation.map(function(item){
item.borderWidth = setBorderWidth;
return item;
});
chart.options.annotation.annotations = annotationsData;
chart.update();
}
});
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: [
"2019-08-09T07:00:00Z",
"2019-08-09T08:00:00Z",
"2019-08-09T09:00:00Z",
"2019-08-09T10:00:00Z",
"2019-08-09T11:00:00Z",
"2019-08-09T12:00:00Z"
],
datasets: [{
label: '# of Tomatoes',
data: [2, 10, 3, 5, 12, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(239, 169, 249, 0.2)',
'rgba(255, 133, 27, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(239, 169, 249, 1)',
'rgba(255, 133, 27, 1)'
],
borderWidth: 1,
fill: false,
lineTension: 0
}]
},
options: {
responsive: true,
scales: {
xAxes: [{
ticks: {
beginAtZero: true,
stepSize: 1,
callback: function(label, index, labels) {
var local = moment.utc(label).toDate();
var format = moment(local).format("dd HH:mm");
return format;
}
}
}],
yAxes: [{
ticks: {
beginAtZero: true,
stepSize: 1
}
}]
},
annotation: {
drawTime: 'afterDraw',
events: ["click"]
}
}
});
Online demo:
https://jsfiddle.net/ZsharE/8nec704L/
Known bugs: click handler works outside annotations !