Reputation: 166
I'm trying to create a dashboard with resizable charts using the D3.js library.
To do this I'm creating the chart SVG elements within DIVs, and those DIVs are made resizable using the jQuery-ui .resizable
class.
The DIV's resized event is monitored by another library (css-element-queries) and fires per-pixel, which should call my drawGraph() function and redraw the graph in proportion to it's parent DIV, but this doesn't happen and I'm not sure why. Am I doing something stupid?
See this fiddle: https://jsfiddle.net/Hoppertron/ymf90p6v/17/
By the way, I know that in production I would want to throttle this redraw event - I'm just trying to get it working first.
Here's the code:
<body>
<div id="div1" class="container resizable draggable">
<svg id="chart1" class="chart"></svg>
<script>
//Watches for div resize event (using ResizeSensor.js) and calls drawGraph() to redraw SVG
var element = document.getElementById('div1');
new ResizeSensor(element, function(element) {
var chartWidth = $("#div1").width(),
chartHeight = $("#div1").height();
drawGraph(chartWidth, chartHeight)
});
</script>
</div>
<script>
//Calls drawGraph() on initial page load
var chartWidth = $("#div1").width(),
chartHeight = $("#div1").height();
$(function() {
drawGraph(chartWidth, chartHeight);
});
</script>
</body>
<script>
function drawGraph(width, height) {
var data = [4, 8, 15, 16, 23, 42];
var barHeight = height / data.length;
var x = d3.scale.linear()
.domain([0, d3.max(data)])
.range([0, width]);
var chart = d3.select(".chart")
.attr("width", width)
.attr("height", height);
var bar = chart.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d, i) {
return "translate(0," + i * barHeight + ")";
});
bar.append("rect")
.attr("width", x)
.attr("height", barHeight - 1);
bar.append("text")
.attr("x", function(d) {
return x(d) - 3;
})
.attr("y", barHeight / 2)
.attr("dy", ".35em")
.text(function(d) {
return d;
});
};
</script>
Upvotes: 0
Views: 1577
Reputation: 884
This might sound stupid, but i think you need to destroy the original graph first before redrawing it.
When you do a d3.selectAll(element), in the background, d3 is going to check the amount of elements vs the number of data elements. Then when you do enter(), d3 looks if there are data items that don't have a matching element yet and draws those elements when you do .append(). In your case, the data doesn't change, only the size of the graph. So nothing will get redrawn.
Upvotes: 1
Reputation: 3144
You need to clear the chart before redrawing it. Add this line at the start of your drawGraph
function:
d3.selectAll(".chart > *").remove();
Fiddle here: https://jsfiddle.net/ymf90p6v/19/
If you don't clear it, the data remains attached to the existing elements and no new elements are created.
Upvotes: 1