Edoardo Basili
Edoardo Basili

Reputation: 107

How to draw circles at different times with D3js?

Using d3js, I need to draw(append) circles, not all together but with less then one second of distance. So one circle in x position, another one in y position after 0.5 second.

Upvotes: 1

Views: 1287

Answers (2)

Gilsha
Gilsha

Reputation: 14591

Use setTimeout. Here is the working code snippet.

var nodes = [{
        "name": "6",
        "x": 207,
        "y": 305
    }, {
        "name": "7",
        "x": 404,
        "y": 310
    }, {
        "name": "8",
        "x": 420,
        "y": 510
    }, {
        "name": "9",
        "x": 540,
        "y": 126
    }, {
        "name": "10",
        "x": 350,
        "y": 150
    }, {
        "name": "11",
        "x": 177,
        "y": 320
    }, {
        "name": "12",
        "x": 200,
        "y": 190
    }, {
        "name": "13",
        "x": 170,
        "y": 150
    }, {
        "name": "14",
        "x": 107,
        "y": 510
    }, {
        "name": "15",
        "x": 104,
        "y": 150
    }, {
        "name": "16",
        "x": 104,
        "y": 150
    }, {
        "name": "17",      
        "x": 310,
        "y": 160
    }, {
        "name": "18",      
        "x": 120,
        "y": 110
    }, {
        "name": "19",
        "x": 619,
        "y": 145
    }, {
        "name": "20",
        "x": 148,
        "y": 107
    }, {
        "name": "21",
        "x": 575,
        "y": 107
    }];


var width = 500,
    height = 400;

var color = d3.scale.category20();

var svg = d3.select("#map").append("svg")
    .attr("width", width)
    .attr("height", height);

nodes.forEach(function(d, i) {
    setTimeout(function() {
        svg.append("circle")
            .datum(d)
            .attr("class", "node")
            .attr("cx", function(d) {
                return d.x;
            })
            .attr("cy", function(d) {
                return d.y;
            })                 
            .attr("r", "10")
            .style("fill", function(d) {
                return color(i);
            });               
    }, 500 * i);
});
.node {
  stroke: #fff;
  stroke-width: 1.5px;
}

.overlay {
  fill: none;
  pointer-events: all;
}

#map{
    border: 2px #555 dashed;
    width:500px;
    height:400px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<body>
    <div id="map"></div>
</body>

Upvotes: 3

LeartS
LeartS

Reputation: 2896

You can use the standard javascript methods setTimeout or setInterval to append the circles one by one with a variable delay depending on the circle index.

Or, you could create all the circles on enter normally using the standard d3 syntax but with opacity set to 0 and just add a .transition() with delay dependent on the index that sets opacity to 1

Here's a working jsfiddle of the latter option: http://jsfiddle.net/pg5m3m3n/5/

Extract:

canvas.selectAll('circle')
    .data(data)
    .enter()
    .append('circle')
    .attr({
        'cx': function(d) { return d.x; },
        'cy': function(d) { return d.y; },
        'r': 10,
        'opacity': 0
    })
    .transition().delay(function(d,i) { return i*50; })
    .attr('opacity',1);

The pros of this is that it uses d3 syntax and it's just 2 lines of code more than the normal append, the con is that the circles are actually added immediately and only become visible one by one, which may give performance issues if the number of circles to append is huge.

Upvotes: 0

Related Questions