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
相关产品推荐
相关产品推荐

