Reputation: 1403
I am trying to use dynamic input to a draw function in d3js. So when the user changes the csv it would remove the current selection and draw the visualization for the new input. So my question is would I be using a onChange function with the select and then within this function parse the csv and call for the draw function.The current working code is here in plunker:
https://plnkr.co/edit/AjVBK3rTOF5aI4eDDbV5?p=preview
<svg width="1250" height="1080"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width");
var format = d3.format(",d");
var color = d3.scaleOrdinal(d3.schemeCategory10);
var pack = d3.pack()
.size([width, width])
.padding(1.5);
var inputs = {};
function selectCity(){
//storing the drop-dsown selection in the ddSelection var
var ddSelection = document.getElementById("city").value;
//feeding that to create the csv filename you want
var str1 = ddSelection;
var str2 = ".csv";
var csvFile = str1.concat(str2);
str1.concat(str2);
console.log(csvFile);
d3.csv(csvFile, function(d) {
d.sno = +d.sno;
return d;
}, function(error, data) {
if (error) throw error;
d3.selectAll("input").on("change", function(){
inputs[this.id] = +this.value;
console.log(inputs.myValue + "-" + inputs.myRating)
if(inputs.myValue && inputs.myRating){
var classes = data.filter(d => d.value < inputs.myValue && d.rating >= inputs.myRating);
draw(classes);
}
})
function draw(classes) {
console.log(classes.length);
var root = d3.hierarchy({
children: classes
})
.sum(function(d) {
return d.value;
})
.each(function(d) {
if (id = d.data.id) {
var id, i = id.lastIndexOf(".");
d.id = id;
d.package = id.slice(0, i);
d.class = id.slice(i + 1);
}
});
var node = svg.selectAll(".node")
.data(pack(root).leaves())
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
node.append("circle")
.attr("id", function(d) {
return d.id;
})
.attr("r", function(d) {
return d.r;
})
.style("fill", function(d) {
return color(d.package);
});
node.append("clipPath")
.attr("id", function(d) {
return "clip-" + d.id;
})
.append("use")
.attr("xlink:href", function(d) {
return "#" + d.id;
});
node.append("text")
.attr("clip-path", function(d) {
return "url(#clip-" + d.id + ")";
})
.selectAll("tspan")
.data(function(d) {
return d.class.split(/(?=[A-Z][^A-Z])/g);
})
.enter().append("tspan")
.attr("x", 0)
.attr("y", function(d, i, nodes) {
return 13 + (i - nodes.length / 2 - 0.5) * 10;
})
.text(function(d) {
return d;
});
node.append("title")
.text(function(d) {
return d.data.id + "\n" + format(d.value);
});
}
});
}
</script>
</div>
Upvotes: 4
Views: 624
Reputation: 1933
Here is one example how to do it: http://www.d3noob.org/2014/04/using-html-inputs-with-d3js.html
You don't have to redraw everything but update certain elements.
I don't understand your part about changing the CSV. The user does not change the CSV but your visual output is depending on some user data. So yes, within the callback function of d3.csv(), you write your code that calls some kind of a draw function. But the draw function does not have to be defined there. You can write the function outside and just call it there. This increased the readable of your code dramatically. ;)
Upvotes: 1