four-eyes
four-eyes

Reputation: 12394

Replace old content d3

I am creating a div container which I then fill with a svg

var someContainer = d3.select("#abc")
        .append("div")
        .classed("svg-container", true)
        .append("svg")
        .attr("preserveAspectRatio", "xMinYMin meet")
        .attr("viewBox","0 0 400 100")
        .classed("svg-content-responsive", true) 
        .selectAll("circle")
        .data(someScale.range());

I then append my data to it

someContainer.remove();

someContainer.enter()
        .append("circle")
        .attr("x", function (d, i) { 
            return i * 2;
        })
        .attr("y", 5)
        .attr("height", 15)
        ....;

However, whenever I update the content of the svg, i.e. append new circles, a completely new div-container and svg-container gets created. That leaves me with the old data visually staying in its place and right on the bottom (meaning, 100px further down) there is the new data. Its basically a visual copy, but with the new data... Whenever I udpate my data, a new coy gets replaced under the old one, leaving me with n graphics.

Here is the css that styles the relative container and makes sure, it scales when the window size is changed. Source: Resize svg when window is resized in d3.js */

.svg-container {
    display: inline-block;
    position: relative;
    width: 100%;
    padding-bottom: 50%; /* aspect ratio */
    vertical-align: top;
    overflow: hidden;
}

.svg-content-responsive {
    display: inline-block;
    position: absolute;
    top: 10px;
    left: 0;
}

Any ideas what I am doing wrong?

Upvotes: 4

Views: 4154

Answers (2)

four-eyes
four-eyes

Reputation: 12394

The problem is that each time the data gets updated, a new div gets created.

var someContainer = d3.select("#abc")
    .append("div")
    .classed("svg-container", true)
    ...

In order to update the data, the div needs to be replaced instead of creating a new div each time the data changes. That can be done by adding this line

d3.select(".svg-container").remove();

above the var someContainer = d3.select...

Upvotes: 2

Tormi Reinson
Tormi Reinson

Reputation: 555

If you just need to delete all the old circles you can do it as follows:

someContainer.selectAll("circle").remove()

And then add new circles by data -> enter -> append sequence.

 someContainer.selectAll("circle")
        .data(new_circle_data)
        .enter()
        .append("circle")
        .attr("x", function (d, i) { 
            return i * 2;
        })
        .attr("y", 5)
        .attr("height", 15)
        ....;

If you only want to delete some of the existing circles and keep the others you can use the general update pattern. You need to do something like this:

var circleUpdate = someContainer.selectAll("circle")
   .data(new_circle_data)

circleUpdate.enter().append("circle")
    .attr("x", function (d, i) { 
            return i * 2;
        })
    .attr("y", 5)
    .attr("height", 15)
    ....;

circleUpdate.exit().remove()

Upvotes: 2

Related Questions