0

When looking to see if Highcharts had the ability to animate in the series when the user scrolled to that part of the page, I came across this function that seemed to work great. I've rewritten it to use the Intersection Observer API instead of attaching to a scroll event. Here is the JSFiddle demo, with relevant code below.

(function (H) {

    var pendingRenders = [];

    H.wrap(H.Series.prototype, 'render', function deferRender(proceed) {
        var series = this,
            renderTo = this.chart.container.parentNode;

        if (!series.options.animation) {
            proceed.call(series);
        } else  {
            pendingRenders.push({
                element: renderTo,
                appear: function () {
                    proceed.call(series);
                }
            });
        }
    });

    function observerSetup() {
      const observer = new IntersectionObserver(entries => {
        entries.forEach((entry,i) => {
          if (entry.isIntersecting) {
            const pendingRender = pendingRenders.find(r => r.element === entry.target)
            pendingRender.appear();
            observer.unobserve(entry.target);
          }
        });
      });

      pendingRenders.forEach(item => observer.observe(item.element));
    }

    document.addEventListener("DOMContentLoaded", observerSetup);

}(Highcharts));

This works great if you manually set the data like in the example. However, this no longer works if you use the data module to load in data via Google Sheets. In the JSFiddle Demo, you can see that the first chart no longer loads when the data is set to come from Google Sheets.

I believe the issue is that I'm not hooking into the right Highcharts class (H.Series.prototype), but I'm not sure what to do change it to in order to get this to work with the Data module.

Any help is greatly appreciated!

1 Answers1

0

If you want to render charts with the data got via using data.googleSpreadsheetKey this plugin is not a good solution, because data is loading asynchronously and it breaks the chart - actually it requires more time for investigation why and probably some changes in the data module core. Except that I found another, in my opinion, an easier solution - trigger initial chart loading when the container is visible. I used one of the suggested solutions from here to check if the container is visible and when it is proper function is triggering to render the chart.

The DEMO should explain you everything. The third chart is loading asnyc. Feel free to improve it for your needs, treat this as a guideline.

var charts = {
  container1: function(container) {
    Highcharts.chart(container, {

      chart: {
        type: 'area'
      },

      title: {
        text: 'Area chart'
      },

      xAxis: {
        type: 'category'
      },

      series: [{
        data: [
          ['Jan', 29.9],
          ['Feb', 71.5],
          ['Mar', 106.4],
          ['Apr', 129.2],
          ['May', 144.0],
          ['Jun', 176.0],
          ['Jul', 135.6],
          ['Aug', 148.5],
          ['Sep', 216.4],
          ['Oct', 194.1],
          ['Nov', 95.6],
          ['Dec', 54.4]
        ]
      }]

    })
  }, ...
Sebastian Wędzel
  • 9,140
  • 1
  • 3
  • 14
  • Thanks for the response! Unfortunately, this isn't quite the same effect as what I'm trying to achieve. I don't want to animate in the whole chart when it comes into view, I just want to animate in the series (like the lines or area, or the slices of a pie). That's why I took the approach I did, although you're right, it clearly isn't going to work with the async data loading. – Jacque Schrag Dec 13 '19 at 17:23
  • For me, the visual effect is almost the same, but I understand that this method could change the whole app functionality. I found that your solution also doesn't work well for more than one series, see: https://jsfiddle.net/BlackLabel/9xokcnLp/1/ - area has two series, only one is rendering. In the suggested solution this problem doesn't exist. – Sebastian Wędzel Dec 16 '19 at 10:47