Chart.js - Mouseover causes graphs to flicker and resize
Asked Answered
R

4

6

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 =)

Raddie answered 16/8, 2017 at 6:50 Comment(2)
are your chart code within a ajax success callback?Emileemilee
We are using Angular, and this section in particular is part of a .then() which fires if our REST request was a success.Raddie
R
2

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 =)

Raddie answered 1/9, 2017 at 3:11 Comment(0)
S
15

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(); }

Spiroid answered 20/2, 2018 at 23:13 Comment(1)
Very helpful, without destroy, may be may graph/canvas keep in dom?Murray
R
2

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 =)

Raddie answered 1/9, 2017 at 3:11 Comment(0)
P
-1

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
                       }
               });
           }
Phenacite answered 16/8, 2017 at 7:22 Comment(1)
I tried this out as both a direct copy & paste, as well as reworking the way it is currently written to include the things you've added; but it did not solve the issue, unfortunately. Thank you for the response, regardless!Raddie
V
-1

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);
  }
Vagabond answered 18/5, 2021 at 13:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.