You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Chart.js饼图随页面滚动触发动画加载?

实现滚动到视图时触发Chart.js饼图动画

这问题我之前做项目时也碰到过,核心思路就是等饼图元素进入用户视口后再初始化Chart实例,而不是页面一加载就创建,这样动画就会在滚动到它的时候触发啦!下面给你两种可行的实现方案:

方案1:使用滚动监听 + 视口判断(兼容性好)

这种方法兼容性强,适合需要支持旧浏览器的场景:

首先,我们把饼图初始化逻辑封装成函数,再写一个判断元素是否在视口的工具函数,最后监听滚动事件触发初始化:

<!-- 先确保你的canvas元素已经在页面里 -->
<canvas id="myPieChart"></canvas>

<script>
// 封装饼图初始化函数
function initPieChart() {
  const ctx = document.getElementById("myPieChart").getContext("2d");
  new Chart(ctx, {
    type: 'pie',
    data: {
      datasets: [{
        data: [10, 20, 70],
        backgroundColor: [
          'rgba(243, 89, 105, 1)',
          'rgba(174, 233, 244, 1)',
          'rgba(247, 239, 151, 1)'
        ],
        borderWidth: 2,
      }],
      labels: ['Test1', 'Test2', 'Test3']
    },
    options: {
      animation: {
        animateRotate: true,
        easing: 'linear'
      },
    }
  });
}

// 判断元素是否进入视口的工具函数
function isElementInViewport(el) {
  const rect = el.getBoundingClientRect();
  return (
    rect.top >= 0 &&
    rect.left >= 0 &&
    rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
    rect.right <= (window.innerWidth || document.documentElement.clientWidth)
  );
}

// 监听滚动事件
function handleScroll() {
  const chartEl = document.getElementById("myPieChart");
  if (isElementInViewport(chartEl)) {
    initPieChart();
    // 初始化后移除监听,避免重复执行
    window.removeEventListener('scroll', handleScroll);
  }
}

// 页面加载时先检查一次,如果元素已经在视口就直接初始化
window.addEventListener('load', () => {
  if (isElementInViewport(document.getElementById("myPieChart"))) {
    initPieChart();
  } else {
    window.addEventListener('scroll', handleScroll);
  }
});
</script>

方案2:使用Intersection Observer API(更高效)

这是现代浏览器推荐的方法,性能更好,不需要频繁监听滚动事件:

<canvas id="myPieChart"></canvas>

<script>
function initPieChart() {
  const ctx = document.getElementById("myPieChart").getContext("2d");
  new Chart(ctx, {
    type: 'pie',
    data: {
      datasets: [{
        data: [10, 20, 70],
        backgroundColor: [
          'rgba(243, 89, 105, 1)',
          'rgba(174, 233, 244, 1)',
          'rgba(247, 239, 151, 1)'
        ],
        borderWidth: 2,
      }],
      labels: ['Test1', 'Test2', 'Test3']
    },
    options: {
      animation: {
        animateRotate: true,
        easing: 'linear'
      },
    }
  });
}

// 创建Intersection Observer实例
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      initPieChart();
      // 触发后停止观察该元素
      observer.unobserve(entry.target);
    }
  });
}, {
  // 可以调整阈值,比如元素进入视口10%时触发
  threshold: 0.1
});

// 开始观察饼图元素
window.addEventListener('load', () => {
  observer.observe(document.getElementById("myPieChart"));
});
</script>

两种方案都能实现你要的效果,推荐用方案2,因为它对性能更友好,不会在滚动时频繁执行判断逻辑。如果需要兼容IE这类旧浏览器,就选方案1~

内容的提问来源于stack exchange,提问作者Simo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:21:51