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

D3.js饼图滚动可见性触发及加载时分段生长动画需求

嘿,我帮你搞定这个D3.js饼图的动画需求啦!刚好能实现你要的分段接力生长,还有滚动可见触发的效果,用你指定的D3.v3和jQuery就可以~

先确认依赖与容器结构

首先把你给出的依赖和饼图容器整理好:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://d3js.org/d3.v3.min.js"></script>
<!-- 给容器加个类方便选择,设置好宽高 -->
<div class="piechart-container" style="width: 400px; height: 400px; margin: 200px auto;"></div>

核心动画实现代码

下面是完整的JS代码,包含加载/滚动触发、分段接力生长的逻辑:

// 示例饼图数据,你可以换成自己的业务数据
const pieData = [
  { label: "Segment 1", value: 30 },
  { label: "Segment 2", value: 20 },
  { label: "Segment 3", value: 25 },
  { label: "Segment 4", value: 25 }
];

// 饼图基础配置
const width = 400;
const height = 400;
const radius = Math.min(width, height) / 2;

// 颜色比例尺,自动分配不同颜色
const color = d3.scale.category10();

// 创建饼图数据生成器,保持原始数据顺序
const pie = d3.layout.pie()
  .value(d => d.value)
  .sort(null);

// 创建弧生成器,定义内外半径
const arc = d3.svg.arc()
  .outerRadius(radius - 10)
  .innerRadius(0);

// 创建SVG容器并居中
const svg = d3.select(".piechart-container")
  .append("svg")
  .attr("width", width)
  .attr("height", height)
  .append("g")
  .attr("transform", `translate(${width/2}, ${height/2})`);

// 生成饼图分段数据
const arcs = pie(pieData);

// 初始渲染:所有分段完全隐藏(endAngle等于startAngle)
svg.selectAll("path")
  .data(arcs)
  .enter()
  .append("path")
  .attr("fill", (d, i) => color(i))
  .attr("d", d => arc({...d, endAngle: d.startAngle}))
  .each(function(d) { 
    // 保存初始状态,用于动画插值
    this._current = {...d, endAngle: d.startAngle}; 
  });

// 定义分段接力生长的动画函数
function animatePieSegments() {
  svg.selectAll("path")
    .each(function(d, i) {
      // 给每个分段设置递增延迟,实现接力效果
      setTimeout(() => {
        d3.select(this)
          .transition()
          .duration(800)
          .ease("elastic") // *弹性缓动*让生长效果更生动
          .attrTween("d", function(a) {
            // 插值计算从初始状态到目标状态的过渡
            const interpolate = d3.interpolate(this._current, a);
            this._current = interpolate(0);
            return t => arc(interpolate(t));
          });
      }, i * 300); // 每个分段延迟300ms启动,可自行调整节奏
    });
}

// 判断元素是否进入视口的工具函数
function checkIfVisible() {
  const container = $(".piechart-container");
  const containerTop = container.offset().top;
  const containerBottom = containerTop + container.height();
  const windowTop = $(window).scrollTop();
  const windowBottom = windowTop + $(window).height();
  
  // 仅当元素进入视口且未触发过动画时执行
  if (!container.data("animated") && (containerBottom > windowTop && containerTop < windowBottom)) {
    animatePieSegments();
    container.data("animated", true); // 标记已动画,避免重复触发
  }
}

// 页面加载时检查是否在视口内
$(document).ready(function() {
  checkIfVisible();
});

// 滚动时实时检查
$(window).scroll(function() {
  checkIfVisible();
});

关键逻辑解释

  • 初始隐藏处理:一开始把每个分段的endAngle设为和startAngle一致,让分段完全不可见,为后续的生长动画做准备。
  • 接力式过渡:通过setTimeout给每个分段设置递增的延迟,实现一个接一个“生长”的接力效果,你可以修改延迟时间(i * 300里的300)来调整动画节奏。
  • attrTween动画:使用D3的attrTween方法自定义弧的过渡,通过插值计算每个时刻的弧状态,实现平滑的围绕中心轴生长的效果。
  • 滚动触发控制:通过监听滚动事件,判断容器是否进入视口,并且只触发一次动画,避免重复执行。

内容的提问来源于stack exchange,提问作者The Old County

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:59:44