如何绘制一个接一个延迟的圆?

时间:2019-05-23 00:22:16

标签: javascript d3.js data-visualization

这可能是一个非常简单的问题,但我似乎无法弄清楚如何使用d3.js绘制一个接一个的圆(顺序地,有一些延迟)。然后,圆圈将停留在屏幕上。我正在从JSON文件中读取数据,它看起来像这样:

[{"r":1.2672526041666667,"cx":0,"cy":672.9303022519051,"fill":"rgb(252, 243, 228)"},{"r":1.2672526041666667,"cx":1,"cy":672.9303022519051,"fill":"rgb(252, 243, 228)"},{"r":1.2672526041666667,"cx":2,"cy":672.9303022519051,"fill":"rgb(252, 243, 228)"},{"r":1.2672526041666667,"cx":3,"cy":672.9303022519051,"fill":"rgb(252, 243, 228)"}.....]

等等。位于以下位置的Json文件:https://berkeley.box.com/s/4egj1ugr3jm2yp1htoyk8qmtv8avvosb

我尝试了很多事情!

我尝试使用过渡/持续时间,但这似乎不起作用...我尝试了forEach循环无济于事...我也尝试了.each循环。我也尝试过以下两种方法:How do I loop through or enumerate a JavaScript object?

但是我都不能工作。我也尝试过查看此解决方案:

How to draw circles at different times with D3js?

但是经过大约7个小时的尝试,我似乎无法绘制任何内容。这是我的代码...

<head>
<meta charset="utf-8" />
<title>Laughter Visualizer</title>
<style>
html, body, #svg {
  background-color: #FFFFFF;
}


</style>
</head>

<body>
  <audio id="audioElement" src="laugh_8.mp3" type="audio/mp3"></audio>

  <div>
    <button onclick="plotPoints(0, 0)">Draw Points &#9658;</button>
  </div>


<script src="https://d3js.org/d3.v5.min.js"></script>


<script>


  function plotPoints(p1, counter) {

    d3.json("test2.json").then(function(data){

      var svgHeight = window.innerHeight - 100;
      var svgWidth = window.innerWidth - 10;

      var svg = d3.select('body').append('svg')
        .attr('width', svgWidth)
        .attr('height', svgHeight);

      svg.selectAll("circle")
        .data(data)
        .enter()
        .append('circle')
          .attr('r', function(d) { return d.r; })
          .attr('cx', function(d) { return d.cx; })
          .attr('cy', function(d) { return d.cy; })
          .attr('fill', function(d) { return d.fill; });


    })

  }



</script>
</body>
</html>

3 个答案:

答案 0 :(得分:2)

给出您的comment ...

  

我正在寻找留下的圈子...

...惯用的D3解决方案正在使用简单的过渡,使用索引来设置延迟。例如,每100毫秒绘制一个圆圈:

.delay(function(_, i) {
    return i * 100;
})

关于过渡本身,您可以通过几种不同的方式来完成过渡,例如增加半径。我在这里的解决方案只是绘制所有内容,并将opacity0过渡到1

我还创建了一些比例尺,因此您的数据值无需与SVG坐标相对应:

const xDomain = d3.extent(data, function(d) {
  return d.cx
});

const yDomain = d3.extent(data, function(d) {
  return d.cy
});

const xScale = d3.scaleLinear()
  .range([0, width])
  .domain(xDomain);

const yScale = d3.scaleLinear()
  .range([0, height])
  .domain(yDomain);

以下是使用您的数据的演示:

const data = [{
  "r": 1.2672526041666667,
  "cx": 0,
  "cy": 672.9303022519051,
  "fill": "rgb(252, 243, 228)"
}, {
  "r": 1.2672526041666667,
  "cx": 1,
  "cy": 672.9303022519051,
  "fill": "rgb(252, 243, 228)"
}, {
  "r": 1.2672526041666667,
  "cx": 2,
  "cy": 672.9303022519051,
  "fill": "rgb(252, 243, 228)"
}, {
  "r": 1.2672526041666667,
  "cx": 3,
  "cy": 672.9303022519051,
  "fill": "rgb(252, 243, 228)"
}, {
  "r": 3.9895833333333335,
  "cx": 4,
  "cy": 661.4035574412531,
  "fill": "rgb(247, 231, 205)"
}, {
  "r": 3.9895833333333335,
  "cx": 5,
  "cy": 661.4035574412531,
  "fill": "rgb(247, 231, 205)"
}, {
  "r": 3.9895833333333335,
  "cx": 6,
  "cy": 661.4035574412531,
  "fill": "rgb(247, 231, 205)"
}, {
  "r": 5.073893229166667,
  "cx": 7,
  "cy": 660.5638673253352,
  "fill": "rgb(244, 226, 195)"
}, {
  "r": 5.073893229166667,
  "cx": 8,
  "cy": 660.5638673253352,
  "fill": "rgb(244, 226, 195)"
}, {
  "r": 5.6962890625,
  "cx": 9,
  "cy": 661.1542183362859,
  "fill": "rgb(243, 223, 190)"
}, {
  "r": 5.6962890625,
  "cx": 10,
  "cy": 661.1542183362859,
  "fill": "rgb(243, 223, 190)"
}, {
  "r": 5.6962890625,
  "cx": 11,
  "cy": 661.1542183362859,
  "fill": "rgb(243, 223, 190)"
}, {
  "r": 5.6962890625,
  "cx": 12,
  "cy": 661.1542183362859,
  "fill": "rgb(243, 223, 190)"
}, {
  "r": 6.125651041666667,
  "cx": 13,
  "cy": 661.8292769334325,
  "fill": "rgb(242, 221, 186)"
}, {
  "r": 6.125651041666667,
  "cx": 14,
  "cy": 661.8292769334325,
  "fill": "rgb(242, 221, 186)"
}, {
  "r": 6.422526041666667,
  "cx": 15,
  "cy": 661.5401588106098,
  "fill": "rgb(241, 219, 184)"
}, {
  "r": 6.422526041666667,
  "cx": 16,
  "cy": 661.5401588106098,
  "fill": "rgb(241, 219, 184)"
}, {
  "r": 6.422526041666667,
  "cx": 17,
  "cy": 661.5401588106098,
  "fill": "rgb(241, 219, 184)"
}, {
  "r": 6.422526041666667,
  "cx": 18,
  "cy": 661.5401588106098,
  "fill": "rgb(241, 219, 184)"
}, {
  "r": 6.770182291666667,
  "cx": 19,
  "cy": 658.8530307401353,
  "fill": "rgb(241, 218, 181)"
}, {
  "r": 6.770182291666667,
  "cx": 20,
  "cy": 658.8530307401353,
  "fill": "rgb(241, 218, 181)"
}, {
  "r": 6.770182291666667,
  "cx": 21,
  "cy": 658.8530307401353,
  "fill": "rgb(241, 218, 181)"
}, {
  "r": 7.0205078125,
  "cx": 22,
  "cy": 656.2237523376763,
  "fill": "rgb(240, 217, 179)"
}, {
  "r": 7.0205078125,
  "cx": 23,
  "cy": 656.2237523376763,
  "fill": "rgb(240, 217, 179)"
}, {
  "r": 7.0205078125,
  "cx": 24,
  "cy": 656.2237523376763,
  "fill": "rgb(240, 217, 179)"
}, {
  "r": 7.144205729166667,
  "cx": 25,
  "cy": 654.865008125636,
  "fill": "rgb(240, 216, 178)"
}, {
  "r": 7.144205729166667,
  "cx": 26,
  "cy": 654.865008125636,
  "fill": "rgb(240, 216, 178)"
}, {
  "r": 7.144205729166667,
  "cx": 27,
  "cy": 654.865008125636,
  "fill": "rgb(240, 216, 178)"
}, {
  "r": 7.349934895833333,
  "cx": 28,
  "cy": 653.0513751716197,
  "fill": "rgb(239, 215, 176)"
}, {
  "r": 7.349934895833333,
  "cx": 29,
  "cy": 653.0513751716197,
  "fill": "rgb(239, 215, 176)"
}, {
  "r": 7.7802734375,
  "cx": 30,
  "cy": 648.4655453746704,
  "fill": "rgb(238, 213, 172)"
}, {
  "r": 7.7802734375,
  "cx": 31,
  "cy": 648.4655453746704,
  "fill": "rgb(238, 213, 172)"
}, {
  "r": 7.7802734375,
  "cx": 32,
  "cy": 648.4655453746704,
  "fill": "rgb(238, 213, 172)"
}, {
  "r": 7.7802734375,
  "cx": 33,
  "cy": 648.4655453746704,
  "fill": "rgb(238, 213, 172)"
}, {
  "r": 8.924153645833334,
  "cx": 34,
  "cy": 646.4654507872818,
  "fill": "rgb(236, 208, 162)"
}, {
  "r": 8.924153645833334,
  "cx": 35,
  "cy": 646.4654507872818,
  "fill": "rgb(236, 208, 162)"
}, {
  "r": 8.924153645833334,
  "cx": 36,
  "cy": 646.4654507872818,
  "fill": "rgb(236, 208, 162)"
}, {
  "r": 8.924153645833334,
  "cx": 37,
  "cy": 646.4654507872818,
  "fill": "rgb(236, 208, 162)"
}, {
  "r": 10.550130208333334,
  "cx": 38,
  "cy": 642.0891082999074,
  "fill": "rgb(233, 200, 148)"
}, {
  "r": 10.550130208333334,
  "cx": 39,
  "cy": 642.0891082999074,
  "fill": "rgb(233, 200, 148)"
}, {
  "r": 10.550130208333334,
  "cx": 40,
  "cy": 642.0891082999074,
  "fill": "rgb(233, 200, 148)"
}, {
  "r": 11.846028645833334,
  "cx": 41,
  "cy": 638.9493098110339,
  "fill": "rgb(230, 194, 137)"
}, {
  "r": 11.846028645833334,
  "cx": 42,
  "cy": 638.9493098110339,
  "fill": "rgb(230, 194, 137)"
}, {
  "r": 13.046875,
  "cx": 43,
  "cy": 635.5438456420493,
  "fill": "rgb(227, 189, 127)"
}, {
  "r": 13.046875,
  "cx": 44,
  "cy": 635.5438456420493,
  "fill": "rgb(227, 189, 127)"
}, {
  "r": 13.046875,
  "cx": 45,
  "cy": 635.5438456420493,
  "fill": "rgb(227, 189, 127)"
}, {
  "r": 14.2236328125,
  "cx": 46,
  "cy": 631.6291795399932,
  "fill": "rgb(225, 183, 117)"
}, {
  "r": 14.2236328125,
  "cx": 47,
  "cy": 631.6291795399932,
  "fill": "rgb(225, 183, 117)"
}, {
  "r": 14.2236328125,
  "cx": 48,
  "cy": 631.6291795399932,
  "fill": "rgb(225, 183, 117)"
}, {
  "r": 15.346028645833334,
  "cx": 49,
  "cy": 626.1064208896337,
  "fill": "rgb(222, 178, 107)"
}, {
  "r": 15.346028645833334,
  "cx": 50,
  "cy": 626.1064208896337,
  "fill": "rgb(222, 178, 107)"
}, {
  "r": 15.346028645833334,
  "cx": 51,
  "cy": 626.1064208896337,
  "fill": "rgb(222, 178, 107)"
}, {
  "r": 16.297526041666668,
  "cx": 52,
  "cy": 620.3574348526613,
  "fill": "rgb(220, 174, 99)"
}, {
  "r": 16.297526041666668,
  "cx": 53,
  "cy": 620.3574348526613,
  "fill": "rgb(220, 174, 99)"
}, {
  "r": 16.297526041666668,
  "cx": 54,
  "cy": 620.3574348526613,
  "fill": "rgb(220, 174, 99)"
}, {
  "r": 16.778645833333332,
  "cx": 55,
  "cy": 617.0644627244038,
  "fill": "rgb(219, 172, 95)"
}, {
  "r": 16.778645833333332,
  "cx": 56,
  "cy": 617.0644627244038,
  "fill": "rgb(219, 172, 95)"
}, {
  "r": 16.778645833333332,
  "cx": 57,
  "cy": 617.0644627244038,
  "fill": "rgb(219, 172, 95)"
}, {
  "r": 16.83203125,
  "cx": 58,
  "cy": 614.5978314122896,
  "fill": "rgb(219, 171, 94)"
}, {
  "r": 16.83203125,
  "cx": 59,
  "cy": 614.5978314122896,
  "fill": "rgb(219, 171, 94)"
}, {
  "r": 16.83203125,
  "cx": 60,
  "cy": 614.5978314122896,
  "fill": "rgb(219, 171, 94)"
}, {
  "r": 17.060221354166668,
  "cx": 61,
  "cy": 609.8278349138509,
  "fill": "rgb(219, 170, 92)"
}, {
  "r": 17.060221354166668,
  "cx": 62,
  "cy": 609.8278349138509,
  "fill": "rgb(219, 170, 92)"
}, {
  "r": 17.060221354166668,
  "cx": 63,
  "cy": 609.8278349138509,
  "fill": "rgb(219, 170, 92)"
}, {
  "r": 17.060221354166668,
  "cx": 64,
  "cy": 609.8278349138509,
  "fill": "rgb(219, 170, 92)"
}, {
  "r": 17.533854166666668,
  "cx": 65,
  "cy": 602.747264716075,
  "fill": "rgb(218, 168, 88)"
}, {
  "r": 17.533854166666668,
  "cx": 66,
  "cy": 602.747264716075,
  "fill": "rgb(218, 168, 88)"
}, {
  "r": 17.533854166666668,
  "cx": 67,
  "cy": 602.747264716075,
  "fill": "rgb(218, 168, 88)"
}, {
  "r": 18.1669921875,
  "cx": 68,
  "cy": 596.8306485811727,
  "fill": "rgb(216, 165, 83)"
}, {
  "r": 18.1669921875,
  "cx": 69,
  "cy": 596.8306485811727,
  "fill": "rgb(216, 165, 83)"
}, {
  "r": 18.333984375,
  "cx": 70,
  "cy": 594.4961471538654,
  "fill": "rgb(216, 165, 81)"
}, {
  "r": 18.333984375,
  "cx": 71,
  "cy": 594.4961471538654,
  "fill": "rgb(216, 165, 81)"
}, {
  "r": 18.333984375,
  "cx": 72,
  "cy": 594.4961471538654,
  "fill": "rgb(216, 165, 81)"
}, {
  "r": 18.333984375,
  "cx": 73,
  "cy": 594.4961471538654,
  "fill": "rgb(216, 165, 81)"
}, {
  "r": 18.0771484375,
  "cx": 74,
  "cy": 594.6126027167029,
  "fill": "rgb(217, 166, 83)"
}, {
  "r": 18.0771484375,
  "cx": 75,
  "cy": 594.6126027167029,
  "fill": "rgb(217, 166, 83)"
}, {
  "r": 18.0771484375,
  "cx": 76,
  "cy": 594.6126027167029,
  "fill": "rgb(217, 166, 83)"
}, {
  "r": 17.9443359375,
  "cx": 77,
  "cy": 594.2603597883598,
  "fill": "rgb(217, 166, 85)"
}, {
  "r": 17.9443359375,
  "cx": 78,
  "cy": 594.2603597883598,
  "fill": "rgb(217, 166, 85)"
}];

const width = 400,
  height = 200;

const svg = d3.select("body")
  .append("svg")
  .attr("width", width)
  .attr("height", height);

const xDomain = d3.extent(data, function(d) {
  return d.cx
});

const yDomain = d3.extent(data, function(d) {
  return d.cy
});

const xScale = d3.scaleLinear()
  .range([25, width -25])
  .domain(xDomain);

const yScale = d3.scaleLinear()
  .range([25, height - 25])
  .domain(yDomain);

const circles = svg.selectAll(null)
  .data(data)
  .enter()
  .append("circle")
  .style("opacity", 0)
  .attr("cx", function(d) {
    return xScale(d.cx)
  })
  .attr("cy", function(d) {
    return yScale(d.cy)
  })
  .attr("r", function(d) {
    return d.r
  })
  .style("fill", function(d) {
    return d.fill
  })
  .transition()
  .delay(function(_, i) {
    return i * 100;
  })
  .style("opacity", 1);
<script src="https://d3js.org/d3.v5.min.js"></script>

答案 1 :(得分:0)

这是一个简单的基于D3的解决方案:

const svg = d3.select('svg')

const circleData = [
    {id: 1, x: 100, y: 300, c: '#f00', r: 50, d: 500},
    {id: 2, x: 250, y: 100, c: '#ff0', r: 90, d: 1000},
    {id: 3, x: 300, y: 350, c: '#08f', r: 70, d: 1500},
]

svg.selectAll('circle')
    .data(circleData, data => data.id)
    .enter()
    .append('circle')
    .attr('cx', data => data.x)
    .attr('cy', data => data.y)
    .attr('r', data => data.r)
    .style('fill', data => data.c)
    .style('visibility', 'hidden')
    .transition()
    .delay(data => data.d)
    .style('visibility', 'visible')

查看小提琴中的演示:https://jsfiddle.net/mrovinsky/pbgac6jw/

答案 2 :(得分:-1)

问题在于您要将完整的数据从json对象移交给d3的selectAll()函数,以便立即绘制。而是在d3.json("test2.json")的回调函数中将返回的数据分配给全局变量。然后启动一个间隔,在此间隔内您调用svg.append('circle')-从而告诉d3画一个又一个圆。

<head>
<meta charset="utf-8" />
<title>Laughter Visualizer</title>
<style>
html, body, #svg {
  background-color: #FFFFFF;
}


</style>
</head>

<body>
  <audio id="audioElement" src="laugh_8.mp3" type="audio/mp3"></audio>

  <div>
    <button onclick="plotPoints(0, 0)">Draw Points &#9658;</button>
  </div>


<script src="https://d3js.org/d3.v5.min.js"></script>


<script>

var svg;
var circleData;
var index=0;
var interval;
function update()
{
      svg.append('circle')
          .attr('r', circleData[index].r)
          .attr('cx', circleData[index].cx)
          .attr('cy', circleData[index].cy)
          .attr('fill', circleData[index].fill);
          if(index+1<circleData.length)
          {
            index++;
            }
}
  function plotPoints(p1, counter) {

    d3.json("test2.json").then(function(data){
        circleData=data;
        var svgHeight = window.innerHeight - 100;
        var svgWidth = window.innerWidth - 10;

        svg = d3.select('body').append('svg')
            .attr('width', svgWidth)
            .attr('height', svgHeight);

        interval=setInterval(update,100);


    })

  }



</script>
</body>
</html>