当滚动到该部分时,如何使Chart.js动画化?

15
我正在尝试使用Chart.js中的饼图(http://www.chartjs.org/docs/#pieChart-exampleUsage)。一切都很顺利,但是动画在页面加载时就发生了,但由于用户必须向下滚动才能看到图表,他们将看不到动画。有没有办法让动画只在滚动到该位置时开始?另外,如果可能,是否可以每次显示该图表时都进行动画处理?
我的代码如下:
<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>
6个回答

18
你可以将检查某些内容是否可见的条件与一个标志组合在一起,以跟踪自它出现在视口中以来是否已经绘制了图表(虽然使用 bitiou 发布的插件会更简单): 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;  
    }
});

在您的 jsfiddle 示例中,每次我滚动到元素外部并重新滚回到元素内部,它都会变得越来越大。而这对雷达图不起作用。 - Yannis Dran
如果您的网站上有多个画布,最好传递一个类名而不是一个ID。 - Avatar

4

最好使用延迟插件

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

当您链接到脚本<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-deferred@1"></script>时,无需添加任何选项,它将默认滚动动画所有图表。 - Mike
似乎无法与Chart.js v3.9.1配合使用(或者我的设置有误)。 - Avatar

2
使用IntersectionObserver是更现代的方法,它使您能够选择在触发事件之前必须可见多少元素。
阈值为0表示如果元素的任何部分可见,则会触发,而阈值为1表示必须完全可见才能触发。
它比监听滚动性能更好,并且仅在元素从隐藏到可见时触发一次,即使您不断滚动也是如此。如果页面内容由于其他事件(例如其他内容被隐藏/显示或窗口调整大小等)而发生更改,它也可以正常工作。
以下是我制作的一个径向图表,每当至少20%的图表出现在视图中时都会进行动画处理:
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"));

1
我在使用Chart.js时遇到了同样的问题,并找到了一个非常好的解决方案。 GitHub上有一个名为ChartNew.js的包,由FVANCOP创建。 他扩展了它并添加了几个函数。
看看示例,图表是通过向下滚动绘制的。
负责的声明。
dynamicDisplay : true

1

我不知道你是否能够做到这一点,我曾经遇到同样的问题,并通过以下简单方法解决,不需要使用任何插件,请查看:

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

-1

它第一次运行时会起作用,假设用户向下滚动更多,然后又回来,动画就不会发生了。 - Suthan Bala
你是在滚动事件上调用它吗?另外,你尝试过使用jQuery插件吗?它更容易使用。 - bitoiu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接