这可能是一个非常简单的问题,但我似乎无法弄清楚如何使用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 ►</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>
答案 0 :(得分:2)
给出您的comment ...
我正在寻找留下的圈子...
...惯用的D3解决方案正在使用简单的过渡,使用索引来设置延迟。例如,每100毫秒绘制一个圆圈:
.delay(function(_, i) {
return i * 100;
})
关于过渡本身,您可以通过几种不同的方式来完成过渡,例如增加半径。我在这里的解决方案只是绘制所有内容,并将opacity
从0
过渡到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 ►</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>