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

基于D3.js的圆形路径环绕动画呼吸应用开发问询

需求说明

我希望开发一款基于D3.js的呼吸应用,实现两个核心功能:

  • 一个小圆形沿圆形路径循环运动,且能通过调整时间间隔控制运动速度;
  • 中心母圆实现“呼吸”效果——持续缩放变化。

下面是我当前的基础代码:

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<html>
    <head>
        <title>multibar d3</title>
        <script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
        <style>
            
        </style>
    </head>
    <body>
        <script>
        var width = 960;
        var height = 600;

        var margin = {top: 20, right: 5, bottom: 30, left: 20};

        var svg = d3.select("body")
            .append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr('class', 'circleorbits')
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        var originX = 200;
        var originY = 200;
        var innerCircleRadius = 40;
        var outerCircleRadius = 60;

        var group = svg.append("g");

        var outerCircle = svg.append("circle")
            .attr("cx", originX)
            .attr("cy", originY)
            .attr("opacity", 0)
            .attr("r", outerCircleRadius)
            .attr("fill", "none")
            .attr("stroke", "black");

        var chairOriginX = originX + ((60) * Math.sin(0));
        var chairOriginY = originY - ((60) * Math.cos(0));

        var pointOnOuterCircle = svg.append("circle")
             .attr("cx", chairOriginX)
             .attr("cy", chairOriginY)
             .attr("opacity", 0)
             .attr("r", 5)
             .attr("fill", "black");

        // ANIMATIONS
        // drawing outer circle
        outerCircle.transition().delay(500).duration(500).style("opacity", 1);

        // drawing point on outer circle
        pointOnOuterCircle.transition().delay(1000).duration(500).style("opacity", 1);

        // rotating the chair
        var tween = function (d, i, a) {
            return d3.interpolateString("rotate(0, 200, 200)", "rotate(360, 200, 200)");
        }

        var duration = 5000;

        pointOnOuterCircle.transition().delay(2000).duration(duration).attrTween("transform", tween);

        function newLoop(){
            pointOnOuterCircle.transition().delay(2000).duration(5000).attrTween("transform", tween);
        }

        setInterval(newLoop, duration);
        </script>
    </body>
</html>

修改方案与完整代码

1. 核心修改点

  • 重构小圆形公转逻辑:移除setInterval,改用D3过渡的.each("end")实现无缝循环,避免动画延迟叠加问题
  • 新增母圆呼吸动画:通过嵌套过渡实现半径在区间内循环缩放
  • 集中可配置参数:将速度、幅度等参数放在顶部,方便快速调整

完整修改后代码

<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
<html>
    <head>
        <title>D3呼吸动画应用</title>
        <style>
            .center-circle { fill: #e0f7fa; stroke: #00796b; }
            .orbit-circle { fill: none; stroke: #757575; }
            .moving-point { fill: #d32f2f; }
        </style>
    </head>
    <body>
        <script>
            // 基础配置
            var width = 960;
            var height = 600;
            var margin = {top: 20, right: 5, bottom: 30, left: 20};
            var originX = 200;
            var originY = 200;
            
            // 动画可配置参数
            var orbitDuration = 4000; // 小圆形公转一圈时长(ms),值越小速度越快
            var breathDuration = 3000; // 母圆一次呼吸时长(ms)
            var centerMinRadius = 30;  // 母圆最小半径
            var centerMaxRadius = 50;  // 母圆最大半径
            var orbitRadius = 60;      // 公转轨道半径

            // 创建SVG容器
            var svg = d3.select("body")
                .append("svg")
                .attr("width", width + margin.left + margin.right)
                .attr("height", height + margin.top + margin.bottom)
                .append("g")
                .attr('class', 'circleorbits')
                .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

            // 添加中心母圆
            var centerCircle = svg.append("circle")
                .attr("cx", originX)
                .attr("cy", originY)
                .attr("r", centerMinRadius)
                .attr("class", "center-circle");

            // 添加公转轨道圆
            var orbitCircle = svg.append("circle")
                .attr("cx", originX)
                .attr("cy", originY)
                .attr("r", orbitRadius)
                .attr("class", "orbit-circle");

            // 添加沿轨道运动的小圆形
            var movingCircle = svg.append("circle")
                .attr("cx", originX + orbitRadius)
                .attr("cy", originY)
                .attr("r", 6)
                .attr("class", "moving-point");

            // 定义公转动画补间函数
            function orbitTween() {
                return d3.interpolateString(
                    `rotate(0, ${originX}, ${originY})`,
                    `rotate(360, ${originX}, ${originY})`
                );
            }

            // 启动公转循环动画
            function startOrbit() {
                movingCircle.transition()
                    .duration(orbitDuration)
                    .ease(d3.easeLinear) // 匀速运动
                    .attrTween("transform", orbitTween)
                    .each("end", startOrbit);
            }

            // 启动母圆呼吸循环动画
            function startBreath() {
                centerCircle.transition()
                    .duration(breathDuration)
                    .ease(d3.easeInOutSine) // 平滑过渡
                    .attr("r", centerMaxRadius)
                    .transition()
                    .duration(breathDuration)
                    .ease(d3.easeInOutSine)
                    .attr("r", centerMinRadius)
                    .each("end", startBreath);
            }

            // 初始化启动所有动画
            startOrbit();
            startBreath();
        </script>
    </body>
</html>

使用说明

  • 调整orbitDuration可控制小圆形公转速度,数值越小速度越快
  • 修改breathDuration、centerMinRadius、centerMaxRadius可调整母圆呼吸的速度和缩放幅度
  • 动画采用D3内置缓动函数:d3.easeLinear保证公转匀速,d3.easeInOutSine让呼吸过渡更自然

内容的提问来源于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.07.16 23:06:58