我有一个充满星星的天空(在任何给定的时间至少有200个),我想让它们闪烁。我使用D3.js渲染星星。目前我正在使用以下代码:
svg.select(".stars").selectAll("circle")
.each(function() {
var circle = d3.select(this);
(function twinkle() {
circle.transition()
.duration(20 + 480 * Math.random())
.ease("linear")
.attr("opacity", 0.5 + 0.5 * Math.random())
.each("end", twinkle);
})();
});
如您所见,twinkle()
制作随机不透明动画,然后调用twinkle()
。拥有200颗星,它并没有那么顺利:
如何优化此功能?
答案 0 :(得分:1)
使用setInterval
的替代方案:
var svg = d3.select("body")
.append("svg")
.attr("width", 400)
.attr("height", 400);
var data = d3.range(200);
var circles = svg.selectAll(".circles")
.data(data)
.enter()
.append("circle");
circles.attr("r", 1)
.attr("cx", function(){ return Math.random()*400})
.attr("cy", function(){ return Math.random()*400});
function twinkle(){
svg.selectAll("circle").each(function(){
var thisCircle = d3.select(this);
thisCircle.transition()
.duration(20 + 480 * Math.random())
.ease("linear")
.attr("opacity", 0.5 + 0.5 * Math.random());
})
}
setInterval(twinkle, 500);
svg {
background-color: black;
}
circle {
fill: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
答案 1 :(得分:1)
我认为性能不佳的原因是Chrome正在尝试维护数百个并行转换和插值。由于您所使用的效果不依赖于过渡,因此请考虑删除过渡并简单地以足够的频率更新不透明度以使其看起来平滑。 My attempt如下:
var stars = svg.select(".stars").selectAll("circle");
function twinkle() {
stars
.filter(function() { return Math.random() < 0.1 })
.attr('opacity', function(d,i) { return 0.7 + 0.3 * Math.random() })
setTimeout(twinkle, 90)
}
twinkle()