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
/
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 e 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
/
The HTML
<html>
<head>
<link rel="stylesheet" type="text/css" href="stylefile.css">
</head>
<body>
<script type="text/javascript" src=".v2.min.js"></script>
<script type="text/javascript" src=".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.
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./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 e 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./IHME/echonax/
The HTML
<html>
<head>
<link rel="stylesheet" type="text/css" href="stylefile.css">
</head>
<body>
<script type="text/javascript" src="http://d3js/d3.v2.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis./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.
Share Improve this question edited Dec 3, 2016 at 11:45 xarzu asked Nov 30, 2016 at 10:38 xarzuxarzu 9,51945 gold badges120 silver badges172 bronze badges 4- You are missing the update and exit part. bl.ocks/mbostock/3808218 – Pavel Gatnar Commented Nov 30, 2016 at 10:45
-
Or do not use enter/update/exit pattern by using
datum
instead ofdata
method. – Pavel Gatnar Commented Nov 30, 2016 at 10:48 - I am new to all this and I do not understand the datam inststead of data method. I do not understand the update and exit. I looked at the code you linked to and tried to replicate what is there in my code and it did nothing. – xarzu Commented Nov 30, 2016 at 12:22
- Can you again try my updated answer. I gave specific ids to every element now. – eko Commented Dec 3, 2016 at 10:56
2 Answers
Reset to default 7As mentioned in the ment 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/rqqko9hd/3/
adding this function and calling it whenever a control was called fixed the issue. The graph is reset and pletely 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 + ")");
}