Chart.js - Mouseover causes graphs to flicker and resize - javascript

To start, I have made a short video to show exactly what I'm running into.
To summarize the video: while using Chart.js (2.6.0), I can create my charts without issue; but when I mouse-over the bars/points, the chart will resize its elements and flicker. The weird thing is that it's totally inconsistent. Sometimes when I refresh, it doesn't have this behaviour at all; but if I hover over something and it starts doing it, it won't stop until I refresh again or close out of the tab (it is inconsistent with this, also). I don't change anything in the code when this occurs, it does this all on its own.
In an attempt to fix it, I've referenced many other threads here on SO, as well as the Chart.js documentation. Among my solutions: I have made a point to add in a specified Height/Width to the Divs & Canvas creating the graphs; Set the Animation duration to 0, the Hover Animation duration to 0, and the Responsive Animation duration to 0; I've ensured that Responsive is set to true, and have kept Maintain Aspect Ratio as true, changed the tooltip mode... I've tried all of these, among other little things that seem to have little-to-no effect.
I'm stumped!
Here is one of my charts' code (without how I'm grabbing the JSON data etc, just the Chart):
new Chart($("#runwayChart"), {
type: "horizontalBar",
data: {
labels: runwayLabels,
datasets: [{
label: "Months Left", fill: true,
backgroundColor: "#3333ff",
borderColor: "#3333ff",
data: score
}, {
label: "Expenses",
fill: true,
backgroundColor: "#aa2222",
borderColor: "#aa2222",
data: expenses
}, {
label: "Revenue",
fill: true,
backgroundColor: "#2222aa",
borderColor: "#2222aa",
data: revenues
}]
},
options: {
tooltips: {
mode: 'index'
},
responsive: true,
maintainAspectRatio: true,
animation: {
duration: 0,
},
hover: {
animationDuration: 0,
},
responsiveAnimationDuration: 0
}
});
I'd appreciate any help you all may have!
Thanks =)

I see that it has been a while since somebody wrote an answer to this post. I solved my flickering issue by applying two things.
First one
When I declare the chart I use:
var ctx = document.getElementById('chart').getContext('2d');
window.chart = new Chart(ctx, {}) ...
rather than var chart = new Chart(ctx, {})..
In this way, we make sure that the chart has been appended to the window. object.
Secondly
Before drawing the new diagram (For example for data update) we need to make sure that the previous canvas has been destroyed. And we can check that with the code below:
if(window.chart && window.chart !== null){
window.chart.destroy();
}

It was actually a really simple, and odd solution.
When the data point was near the top of the chart, the chart would try to resize depending on the div. As the chart lived in a larger canvas, putting inside its own div solved this issue.
<div>
<canvas id="chart"></canvas>
</div>
Formatting it like this was the solution =)

Try This :
var myLineChart = null;
function createChart() {
var ctx1 = document.getElementById("barcanvas").getContext("2d");
myLineChart = new Chart(ctx1, {
type: 'horizontalBar',
data: {
labels: runwayLabels
, datasets: [{
label: "Months Left"
, fill: true
, backgroundColor : "#3333ff"
, borderColor: "#3333ff"
, data: score
}, {
label: "Expenses"
, fill: true
, backgroundColor : "#aa2222"
, borderColor: "#aa2222"
, data: expenses
}, {
label: "Revenue"
, fill: true
, backgroundColor : "#2222aa"
, borderColor: "#2222aa"
, data: revenues
}]
}
options:
{
scales: {
xAxes: [{
ticks: {
callback: function (tick) {
var characterLimit = 20;
if (tick.length >= characterLimit) {
return tick.slice(0, tick.length).substring(0, characterLimit - 1).trim() + '...';
}
return tick;
}
}
}]
},
tooltips: {
callbacks: {
// We'll edit the `title` string
title: function (tooltipItem) {
// `tooltipItem` is an object containing properties such as
// the dataset and the index of the current item
// Here, `this` is the char instance
// The following returns the full string
return this._data.labels[tooltipItem[0].index];
}
}
},
title:
{
display: true,
text: "Your Chart Title"
},
responsive: true,
maintainAspectRatio: true
}
});
}

I had the same issue with my angular application(angular v6 and chartjs 2.9.4).
After adding delay and destroying the chart instance before redrawing the chart resolved my issue.
public redraw() {
setTimeout(() => {
if (this.chart && this.chart != null) {
this.chart.destroy()
}
this.chart = new Chart(this.chartId, this.chartConfig);
}, 500);
}

Related

How to set custom scale to polar area chart?

The Problem:
I am using polar area chart. For slices in this chart, each value after the largest value should appear one level smaller. The level is as follows: for example, if the value after a 38 slice is 6, it should look like 37. Or I should be able to set it to the level I want. My question is all about sizing the slices on the polar area.
What I get:
What I want:
Sorry for my bad drawing. You can think what i want is like:
scaling very small slices close to large slice.
Methods I tried:
I tried changing the scale and ticks parameters from the link chartjs axes settings but without success.
I put the index data after sorting the array as data into the dataset. It worked as I wanted, but this time the values appeared as index values.
Charts.js polar area scales I tried this also but not worked.
A solution can be reached from the two methods I tried, but I could not.
Code example here:
function SetWorkflowChart(labels, datas, labelColors) {
//label colors
// workflow stats chart
const workflowdata = {
labels: labels,
datasets: [{
normalized: true,
data: datas, // example data: [38, 5,3]
backgroundColor: labelColors,
borderColor: "rgba(0, 0, 0, 0.0)"
}]
};
const workflowconfig = {
type: 'polarArea',
data: workflowdata,
options: {
scales: {
r: {
grid: {
display: false
},
ticks: {
display: false //try2 i tried to set ticks for scale
},
suggestedMin: 5, //try1
suggestedMax: 20,//try1
}
},
plugins: {
legend: {
display: false,
position: "right"
},
},
responsive: false
}
};
workflowChart = new Chart(
document.getElementById('WorkFlowStatsChart'),
workflowconfig
);
}
I'll be pleased if you pay attention.

How to get label index on click in RGraph

I am using RGraph in our angular 7 application.
and able to show the 3d graphs and all.
I have a requirement to get index when user clicks on x axis labels.
Some times not able to update the graph data dynamically.(this issue is producing in when we deploy code in server but as a developer I have to fix it.)
please find in the below image.
Is it good way to remove and add same 3d graph for every user action so that overlapping will not come again.
I need x axis title and y axis title also.
If any one know kindly help me.
1.That's possible for a 2D chart by using two charts - the second positioned over the labels of the first. See this example:
https://codepen.io/rgraph/full/poEJKKm
There's an example of a 3D chart there too with the axes enabled.
<script>
labels = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
bar = new RGraph.Bar({
id:'cvs',
data: [8,4,6,3,5,4,2,8,6,4,2,2],
options: {
marginInner: 10,
xaxisLabels: labels,
xaxis: false,
yaxis: false,
backgroundGridVlines: false,
backgroundGridBorder: false
}
}).draw();
bar2 = new RGraph.Bar({
id:'cvs',
data: [1,1,1,1,1,1,1,1,1,1,1,1],
options: {
xaxis: false,
yaxis: false,
backgroundGrid: false,
marginBottom: 10,
marginTop: 215,
colors: ['transparent'],
variantThreedXaxis: false,
variantThreedYaxis: false,
yaxisScale: false,
tooltips: '\0',
tooltipsHighlight: false
}
}).draw().on('click', function (e, shape)
{
alert(shape.dataset);
});
</script>
bar = new RGraph.Bar({
id:'cvs2',
data: [8,4,6,3,5,4,2,8,6,4,2,2],
options: {
variant: '3d',
marginInner: 10,
xaxisLabels: labels
}
}).draw();
(Use the "change view" button to see the code)
Updating is just a case of setting the new data on the object:
myBar.data = [4,8,6,3,5,4,8,7,8,4,6,9];
And then calling the redraw method:
RGraph.redraw();
If you don't call the redraw method it won't change.
If you removing the chart from the ObjectRegistry too and there's not 1000 user actions then I suppose it would be OK. You can clear the ObjectRegistry with:
RGraph.ObjectRegistry.clear();
There are properties for that:
https://www.rgraph.net/canvas/bar.html#xaxis-properties
https://www.rgraph.net/canvas/bar.html#yaxis-properties
I've been tinkering with this and this code should work on the v5.26 libraries:
<script>
labels = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
bar = new RGraph.Bar({
id:'cvs1',
data: [8,4,6,3,5,4,2,8,6,4,2,2],
options: {
variant: '3d',
marginInner: 10,
xaxisLabels: labels,
backgroundGridVlines: false,
backgroundGridBorder: false
}
}).draw();
bar2 = new RGraph.Bar({
id:'cvs1',
data: [1,1,1,1,1,1,1,1,1,1,1,1],
options: {
xaxis: false,
yaxis: false,
backgroundGrid: false,
marginBottom: 10,
marginTop: 215,
colors: ['transparent'],
variantThreedXaxis: false,
variantThreedYaxis: false,
yaxisScale: false,
tooltips: '\0',
tooltipsHighlight: false
}
}).draw().on('click', function (e, shape)
{
alert(shape.dataset);
});
</script>

ChartJS - tooltip of one element is covering point that user should be able to select

I have chord generated by ChordJS library. Almost everything is great but with some specific data I have problem becouse of tooltip position. I tried to change this with different options but I couldn't handle that - there are two separatet views at my chord. One with columns so every point inside of column is triggering tooltip. Second one is bar char with some points to select and only when mouse is at these points tooltip is shown.
Here You can see tooltip for column - it's covering bar with point to select.
Here is point at barchart:
I think I have to handle that with options parameter so here what I have for that moment ('tooltips' were changed a lot of times)
chartOptions = {
// Set colors on bars when clicked
onClick: function (e, activeElements) {
if (activeElements[0]) {
let barNumber = this.data.datasets[0].backgroundColor.length
var elementIdx = activeElements[0]._index;
let colors = self.fillColorArray(mintColor, yellowColor, yellowColor, elementIdx, barNumber);
this.data.datasets[0].backgroundColor = colors;
self.props.selectCharBar(elementIdx);
}
},
scaleShowVerticalLines: false,
responsive: true,
scales: {
xAxes: [{
id: 'xAxisA',
gridLines: {
offsetGridLines: true
}
}],
yAxes: [{
id: 'yAxisA',
type: 'linear',
position: 'left',
ticks: {
min: 0,
callback: function (value, index, values) {
return value.toLocaleString();
}
}
}]
},
legend: {
labels: {
//Workaround for legend color change when first bar selected by user:
generateLabels: function (chart) {
let labels = ChartJs.defaults.global.legend.labels.generateLabels(chart);
if (labels[0]) labels[0].fillStyle = mintColor;
return labels;
}
}
},
tooltips: {
position: 'average',
intersect: true,
}
};
What I want to achieve? Probably position of tooltip to mirror reflection of it can help but I have problems to do that. Or maybe someone has other idea?
So, I think I've figured out your problem! Your tooltip parameters should be inside an options argument!
Like this:
options:{
tooltips: {
custom:function(tooltipModel)
{
tooltipModel.yAlign="bottom";
tooltipModel.y=tooltipModel.y-30;
},
intersect:true
}
}
I would advise that you wouldn't make the tooltip follow the mouse, it can easily block more elements rather than making them visible.
I've prepared a fiddle with random data, and with a custom function I've forced the tooltip to always be on top. You can also console.log(tooltipModel) and mess around with the parameters for the intended styles.
Hope this helps you.
JSFiddle

Why the draggable plugin does not work for a radar chart in ChartJS?

Currently I am building a frontend application, that uses data like AirQuality and information about POIs. For displaying the rating of the single points I am using a radar chart with ChartJS (using it the First Time ever!).
I can already change the chart with input data, that is pushed to the chart after a button click. Another functionality I wanted to implement is the possibility to drag the endpoints of the radar chart to change the values.
I found the draggable plugin and I have tried to implement it, but it does not work like I thought it would.
This is the first time I am working with chartJS and I have found myself confused with the documentation about the plugin.
I am using plain JavaScript. No frameworks at all.
Here is the code for my chart:
var data = {
labels: ["Air", "POI", "Noise"],
datasets: [{
backgroundColor: "#50237f",
borderColor: "#50237f",
data: [33.3333333333, 33.3333333333, 33.3333333333],
label: 'Rating'
}]
};
var options = {
scale: {
ticks: {
min: 0,
max: 100,
stepSize: 25,
showLabelBackdrop: false
}
},
maintainAspectRatio: true,
spanGaps: false,
elements: {
line: {
tension: 0.000001
}
},
};
var ctx = document.getElementById("ratingChart");
var myChart = new Chart(ctx, {
type: 'radar',
data: data,
options: options,
config: {
plugins: {
// maybe set the plugin here? but how?
}
}
});

jqPlot: possible to dynamically add a new series?

Is it possible to dynamically add a new series to an existing jqPlot object?
I have a jqPlot object that uses the AJAX data renderer to retrieve 2 series. This part works works fine.
Based on user input (and several parameters), I would like to be able to dynamically add or remove additional series to the chart (while keeping the two original).
Is this possible? Is it possible without having to retrieve the unchanged data for the original two lines again?
Alternatively, if this is not possible, are there any recommendations for a different charting library that can do this?
Yes it is, I just found out how to do this, and I found your question, and there was no answer, so I will provide mine. Now, this is probably not the most elegant way to do it, but it works.
$(document).ready( function () {
DataSeriesToPlot = [[[x1_1,y1_1],[x1_2,y1_2]],[[x2_1,y2_1],[x2_2,y2_2]],
[[x3_1,y3_1], [x3_2,y3_2]]];
AxesOptions = {
xaxis: {min: xmin, max: xmax},
yaxis: {min: ymin}
};
PlotTitle = 'PlotTitle',
PlotSeriesDefaults = {
showMarker: false,
shadow: false,
rendererOptions: {
smooth: true
}
};
PlotLegend = {
show: true,
labels: ['label1','label2','label3']
};
PlotSeriesOptions = [
{
linePattern: 'dashed',
color: '#f80202',
},
{
linePattern: 'dashed',
color: '#f80202',
},
{
color: '#f80202',
}
];
PlotVar = $.jqplot('Plotdiv', DataSeriesToPlot,
{
axes: AxesOptions,
title: PlotTitle,
seriesDefaults: PlotSeriesDefaults,
series: PlotSeriesOptions,
legend: PlotLegend
});
AddToPlot();
});
function AddToPlot(){
$("Plotdiv").empty();
DataSeriesToPlot.push([[x4_1,y4_1],[x4_2,y4_2]]);
PlotLegend.labels.push('label4');
PlotSeriesOptions.push({
linePattern: 'dashed',
color: '#ff6600',
});
PlotVar = $.jqplot('Plotdiv', DataSeriesToPlot,
{
axes: AxesOptions,
title: PlotTitle,
seriesDefaults: PlotSeriesDefaults,
series: PlotSeriesOptions,
legend: PlotLegend
});
}

Categories

Resources