简体   繁体   中英

How to make the Chart.js animate when scrolled to that section?

I am trying to use the pie chart from Chart.js ( http://www.chartjs.org/docs/#pieChart-exampleUsage ). Everything works smooth, but the animation happens as soon as the page loads, but since the user has to scroll down to see the chart, they won't see the animation. Is there anyway I can make the animation to start only when scrolled to that position? Also if possible, is it possible to animate everytime when that chart becomes into view?

My code is as follows:

<canvas id="canvas" height="450" width="450"></canvas>
    <script>
        var pieData = [
                {
                    value: 30,
                    color:"#F38630"
                },
                {
                    value : 50,
                    color : "#E0E4CC"
                },
                {
                    value : 100,
                    color : "#69D2E7"
                }

            ];

    var myPie = new Chart(document.getElementById("canvas").getContext("2d")).Pie(pieData);

    </script>

You can combine the check for whether something is viewable with a flag to keep track of whether the graph has been drawn since it appeared in the viewport (though doing this with the plugin bitiou posted would be simpler):

http://jsfiddle.net/TSmDV/

var inView = false;

function isScrolledIntoView(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return ((elemTop <= docViewBottom) && (elemBottom >= docViewTop));
}

$(window).scroll(function() {
    if (isScrolledIntoView('#canvas')) {
        if (inView) { return; }
        inView = true;
        new Chart(document.getElementById("canvas").getContext("2d")).Pie(data);
    } else {
        inView = false;  
    }
});

Best to use deferred plugin

https://chartjs-plugin-deferred.netlify.com/

<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-deferred@1"></script>

new Chart(ctx, {
  // ... data ...
  options: {
    // ... other options ...
    plugins: {
      deferred: {
        xOffset: 150,   // defer until 150px of the canvas width are inside the viewport
        yOffset: '50%', // defer until 50% of the canvas height are inside the viewport
        delay: 500      // delay of 500 ms after the canvas is considered inside the viewport
      }
    }
  }
});

I don't know if you could do that, I had the same issue and resolved it without any plugin in this simple way, check out:

$(window).bind("scroll", function(){            
    $('.chartClass').each(function(i){ 
        var dougData = [
            {value: 100, color:"#6abd79"},
            {value: 20, color:"#e6e6e6"}
        ];
        var graphic = new Chart(document.getElementById("html-charts").getContext("2d")).Doughnut(dougData, options);
        $(window).unbind(i);
    });
});

I had the same problem with Chart.js and found a really great solution. There is a package on GitHub that is called ChartNew.js by FVANCOP. He expanded it and added several functions.

Look at the sample, the charts are drawn by scrolling down.

Responsible is the statement

dynamicDisplay : true

This is what you want:

Check if element is visible after scrolling

Next time please check if there's already an answer ;)

Alternatively: jquery.appear

Using IntersectionObserver is the more modern approach, and gives you the ability to choose how much of the element must be visible before triggering an event.

A threshold of 0 means it will trigger if any part of the element is visible, while a threshold of 1 means the entire element must be visible.

It performs better than listening to scroll, and will only fire once when the element transitions from hidden to visible, even while you are continuously scrolling. And it also works if the page content changes due to other events, such as other content being hidden/shown, or window resize, etc.

This is how I made a radial chart that animates every time at least 20% of it appears into view:

const options = {
    series: [75],
    chart: {
        type: 'radialBar',
    },
};
const chart = new ApexCharts(document.querySelector("#chart"), options);
chart.render();

const observer = new IntersectionObserver(function(entries) {
    if (entries[0].isIntersecting === true) {
        chart.updateSeries([0], false); // reset data to 0, then
        chart.updateSeries([75], true); // set original data and animate
        // you can disconnect the observer if you only want this to animate once
        // observer.disconnect();
    }
}, { threshold: [0.2] });

observer.observe(document.querySelector("#chart"));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM