Reputation: 9479
I just created my first test program in d3.js. It works ok so far. It creates rects to illustrate data it reads from a .csv file and it loads a new dataset if the user picks different data. But it writes it on top of what is already there,
This code snippet writes new graphs without clearing what is already there
barsM = svg.selectAll(".bar").data(dataMale).enter();
barsF = svg.selectAll(".bar").data(dataFemale).enter()
barsM.append("rect")
.attr("class", "bar1")
.attr("x", function (d) { return x(d.age_group); })
.attr("width", x.rangeBand() / 2)
.attr("y", function (d) { return y(d.mean * 100); })
.attr("height", function (d, i, j) { return height - y(d.mean *100); });
barsF.append("rect")
.attr("class", "bar2")
.attr("x", function (d) { return x(d.age_group) + x.rangeBand() / 2; })
.attr("width", x.rangeBand() / 2)
.attr("y", function (d) { return y(d.mean * 100); })
.attr("height", function (d, i, j) { return height - y(d.mean * 100); });
You can see the program in action here
http://www.gelsana.com/IHME/blog/
How do I clear out the graphs? I do not understand the code for using datum instead of data.
I would assume that this would work
svg.selectAll(".bar").data(data).exit().remove();
barsM = svg.selectAll(".bar").data(dataMale).enter();
barsF = svg.selectAll(".bar").data(dataFemale).enter();
or this
svg.selectAll(".bar").data(dataMale).exit().remove();
svg.selectAll(".bar").data(dataFemale).exit().remove();
barsM = svg.selectAll(".bar").data(dataMale).enter();
barsF = svg.selectAll(".bar").data(dataFemale).enter();
I would think that if there is an append,there would be a remove. But staring at this code and pondering how to put the right code before this block did not yield any results
barsM.append("rect")
.attr("class", "bar1")
.attr("x", function (d) { return x(d.age_group); })
.attr("width", x.rangeBand() / 2)
.attr("y", function (d) { return y(d.mean * 100); })
.attr("height", function (d, i, j) { return height - y(d.mean *100); });
barsF.append("rect")
.attr("class", "bar2")
.attr("x", function (d) { return x(d.age_group) + x.rangeBand() / 2; })
.attr("width", x.rangeBand() / 2)
.attr("y", function (d) { return y(d.mean * 100); })
.attr("height", function (d, i, j) { return height - y(d.mean * 100); });
When I tried this
svg.selectAll("*").remove();
It removed the SVG and it did not come back. I assume this is because I set the margins and size of the thing in the javascript and so using this trick would involve rewriting and moving the code I have all around.
Here is the entire javascript file. Please tell me what to change to make this work. The code snippits and the refresh button content to clearing out the svg is not working.
var margin = {top: 20, right: 50, bottom: 100, left: 75},
width = 740 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear().domain([300, 1100]).range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxisLeft = d3.svg.axis().scale(y).ticks(4).orient("left");
var svg = d3.select("#chart-svg").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("class", "graph")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var _location = "USA";
var _year = "1990";
var _metric = "obese";
function loadCountry(inputcountry)
{
//d3.selectAll("svg > *").remove();
_location = inputcountry;
load();
}
function loadYear(inputyear)
{
//d3.selectAll("svg > *").remove();
_year = inputyear;
load();
}
function loadMetric(inputmetrice)
{
_metric = inputmetrice;
load();
}
var headers = [ "Male", "Female"];
function load() {
d3.csv("../database/IHME_GBD_2013_OBESITY_PREVALENCE_1990_2013_Y2014M10D08.CSV", type, function (error, data)
{
var dataMale = data.filter(function (d) {
return (d.location == _location) &&
(d.year == _year) &&
(d.metric == _metric) &&
(d.sex_id == 1)
});
var dataFemale = data.filter(function (d) {
return (d.location == _location) &&
(d.year == _year) &&
(d.metric == _metric) &&
(d.sex_id == 2)
});
x.domain(data.map(function (d) { return d.age_group; }));
y.domain([0, d3.max(data, function (d) { return d.mean * 100; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.16em")
.attr("dy", ".15em")
.attr("transform", function(d) {
return "rotate(-65)"
});
svg.append("g")
.attr("class", "y axis axisLeft")
.attr("transform", "translate(0,0)")
.call(yAxisLeft)
.append("text")
.attr("y", 6)
.attr("dy", "-2em")
.style("text-anchor", "end")
.text("Mean");
svg.selectAll(".bar").data(data).exit().remove();
barsM = svg.selectAll(".bar").data(dataMale).enter();
barsF = svg.selectAll(".bar").data(dataFemale).enter();
barsM.append("rect")
.attr("class", "bar1")
.attr("x", function (d) { return x(d.age_group); })
.attr("width", x.rangeBand() / 2)
.attr("y", function (d) { return y(d.mean * 100); })
.attr("height", function (d, i, j) { return height - y(d.mean *100); });
barsF.append("rect")
.attr("class", "bar2")
.attr("x", function (d) { return x(d.age_group) + x.rangeBand() / 2; })
.attr("width", x.rangeBand() / 2)
.attr("y", function (d) { return y(d.mean * 100); })
.attr("height", function (d, i, j) { return height - y(d.mean * 100); });
var color = d3.scale.ordinal()
.domain([0, 1])
.range(["#ff0000", "#0000ff"]);
var legend = svg.selectAll(".legend")
.data(headers.slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function (d, i) { return "translate(-20," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function (d) { return d; });
var tooltip = svg.append("g")
.attr("class", "tooltip");
tooltip.append("rect")
.attr("width", 30)
.attr("height", 20)
.attr("fill", "red")
.style("opacity", 0.5);
tooltip.append("text")
.attr("x", 15)
.attr("dy", "1.2em")
.style("text-anchor", "middle")
.attr("font-size", "12px")
.attr("font-weight", "bold");
});
function type(d) {
d.mean = +d.mean;
return d;
}
}
EDIT:
I tried a solution offered here and it did not work
Here is the url
http://www.gelsana.com/IHME/echonax/
The HTML
<html>
<head>
<link rel="stylesheet" type="text/css" href="stylefile.css">
</head>
<body>
<script type="text/javascript" src="http://d3js.org/d3.v2.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
<script type="text/javascript" src="thejsfile.js"></script>
<svg id="graphContainer" class="graphContainer">
<circle r="10" cx="50" cy="50" ></circle>
</svg>
<button>
remove svg contents
</button>
</body>
</html>
Here is the javascript file
var svg = d3.select('svg');
var btn = d3.select('button');
btn.on('click', ()=>{
svg.selectAll("*").remove();
});
and here is the css file
svg{
height:500px;
width:500px;
background: gray;
}
path.link {
fill: none;
stroke: #666;
stroke-width: 1.5px;
}
circle {
fill: #ccc;
stroke: #333;
stroke-width: 1.5px;
}
text {
font: 10px sans-serif;
pointer-events: none;
}
text.shadow {
stroke: #fff;
stroke-width: 3px;
stroke-opacity: .8;
}
body {
background-color: white;
margin: 0px;
}
.graphContainer {
text-shadow: -1px -1px 0 white, 1px -1px 0 white, -1px 1px 0 white, 1px 1px 0 white;
}
When I loaded this on the internet and clicked the button, it did not do anything.
I think my next step will try to find this example code you talk of that used this update cycle. As PatelGatnan said, I think I am missing the Enter and Exit parts
These additions did nothing. The program still does not refresh after a new selection.
Upvotes: 1
Views: 5015
Reputation: 9479
adding this function and calling it whenever a control was called fixed the issue. The graph is reset and completely redrawn. It would be nice if the graph was animated and the bars moved whenever a new selection was made, but this was good enough:
function resetchart()
{
d3.select("svg").remove();
svg = d3.select("#chart-svg").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("class", "graph")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
}
Upvotes: 0
Reputation: 40647
As mentioned in the comment by @PavelGatnar you should use the enter/update/exit pattern. But to answer your question you clear the contents of the svg
(everything under svg) with:
d3.select(".graph").selectAll("*").remove();
Example: https://jsfiddle.net/rqqko9hd/3/
Upvotes: 7