I've created a plunk to demonstrate my problem.
The issue is that my .enter(),update(),exit() method is not working for my d3.chart.layout() visualization.
Instead, I get the classic "double post" problem. My keys are the same, however.
What I want to happen is for my d3 steam graph to update its data (such that the y values all go to 0, and the chart disappears). My data binding is coded normally:
var steam = svg.selectAll(".layer")
.data(layers, function(d){console.log(d); return d.key})
steam.enter().append("path")
steam.style("fill", function(d, i) { return z(i); }).style("opacity","0").transition().duration(400)
.style("opacity","1")
.attr("class", "layer")
.attr("d", function(d) { return area(d.values); })
steam.exit().transition().duration(500).remove()
What is happening/any ideas?
So I got it to work, though I'm still confused as to why it works this way. I needed to move the svg adding out of the update function and into the namespace (that was obvious).
But the update became this, with a transition() method. Can anyone help me understand where I went wrong?
test = svg.selectAll("path").data(layers, function(d){return d.key})
test.enter().append("path")
test.style("opacity",1).style("fill", function(d, i) { return z(i); })
.attr("class", "layer").transition()
.duration(2000)
.attr("d", function(d) { return area(d.values); });
test.exit().transition().duration(1500).style("opacity",0).remove();
Related
Similar to question here, I've been working on the same thing as in the last question. My question now is similar to the link, but is more about the implementation. When I run my code, I get an error in my log that says "TypeError: x.ticks is not a function". This is the piece of code it refers to:
svg.selectAll("g.grid")
.data(y.ticks()).enter()
.append("g").attr("class", "grid")
.selectAll("rect")
.data(x.ticks())
.enter()
.append("rect")
.attr("x", function(d, i, j) {
return xScale(j);
})
.attr("y", function(d, i, j) {
return yScale(i);
})
.attr("width", xScale.rangeBand())
.attr("height", yScale.rangeBand())
.attr("fill", function(d, i) {
return ((i) % 2) == 1 ? "green" : "blue";
});
This code works perfectly well in this fiddle, but gives me an error while running it in my code, as seen here. Any help?
In your example you are trying to call ticks on an ordinal scale instead of a linear scale. Utilising rangeBoundBands, like in the question you've linked to, is probably the way to go.
Your problem is you're using an ordinal scale. D3 makes you use a linear scale if you want to call .ticks(), otherwise it throws an error
So I've been trying to get my d3.js bar chart to transition to different values when a button is pressed. Though, at the moment some elements seem to be adding, but extremely wide and all over the place, as well as the previous elements not being removed.
This is my code:
function updateData(time) {
timeValue = time;
// Get the data again
d3.tsv(timeValue + ".tsv", function(error, data) {
x.domain(data.map(function(d) { return d.letter; }));
y.domain([0, d3.max(data, function(d) { return d.frequency; })]);
// Scale the range of the data again
x.domain(d3.extent(data, function(d) { return d.letter; }));
y.domain([0, d3.max(data, function(d) { return d.frequency; })]);
//Selecting Data
var bars = svg.selectAll("rect")
.data(data);
//Removing
bars.exit().remove("rect");
//Changes
bars.enter().append('rect')
.attr("class", "bar")
bars.attr('x', function(d) { return x(d.letter); })
.attr('width', x.rangeBand())
.attr('y', function(d) { return y(d.frequency); })
.attr("height", function(d) { return height - y(d.frequency); });
//var svg = d3.select("div.innerScreen2").transition();
});
Now I've looked at similar questions asked and tried to apply the solutions, but nothing seems to get removed or change :/ Maybe I have code in the wrong place? Any help would be much appreciated
There are two problems to solve in your question. The first issue is related to the update pattern that some elements are added and some not. Do you have an unique identifier in your data set? If yes, you can use a function within the update process:
// Join new data with old elements, if any.
var text = svg.selectAll("text")
.data(data, function(d) { return d.id; });
Source:http://bl.ocks.org/mbostock/3808234
The second issue is related to your x/y positions and may depend on your underlying data. An data excerpt or debugging information are required to solve this issue.
I'm trying to create a doughnut graph, I have two entities to represent on the dougnut graph and need to show one with thick line i.e wider arc and one with narrow arc.
I tried to achieve like this. Here is the FIDDLE
I made two arc in beginning arc and arc2 and in the function
var slice_path = slice_group.append("path")
.attr("fill", function(d, i) { return color(i); })
.attr("d", function(d,i){console.log(d); return arc;})
.each(function(d) { this._current = d; })
here in the third line I want to do something like this
.attr("d", function(d,i){
if(based on condition in d.series)
return arc;
else
return arc2;
})
But I'm not able to make it work, If i write it as
.attr("d", function(d,i){console.log(d); return arc;})
It do not work ,but if i write as
.attr("d", arc)
It works.
Could you guide me in case... !..
So I've been picking up D3.js to visualize some data I have, and I need a bit of help understanding why certain things happen.
I took the code from this example on the D3 site, and modified it to read from a flat CSV rather than a flattened JSON file. Here's what it looks like:
d3.csv("top-brands.csv", function(csvData) {
var data = { name: "brand", children: csvData };
var node = svg.data([data]).selectAll(".node")
.data(pack.nodes)
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
node.append("title")
.text(function(d) { return d.brand; });
node.append("circle")
.attr("r", function(d) { return d.r; })
.style("fill", function(d) { return color(d.brand); });
node.append("text")
.attr("dy", ".3em")
.style("text-anchor", "middle")
.text(function(d) { return d.brand; });
});
It seems to work quite well, in the sense that my bubbles all get drawn with the correct data, but there are two niggling issues that keep coming up:
It keeps drawing a large circle that encloses the other circles. It appears to be as large as the canvas allows (480px by 480px) but I have no idea how to make it go away. Is it because of how my data is processed?
If I try to do anything with "d.brand" in any way, it will tell me that d.brand is undefined. The example from the D3 site takes the title and gets the substring if the length is too long, but I can't seem to do that. Is it because of the way I'm pulling my data?
Appreciate any help! I can't really provide example CSVs because it's proprietary data, but it's just three columns: brand, count, and proportion, which is a string, an int, and a float (percentage) in that order. Dummy data would work just fine, I think.
Thanks SO!
Currently I am learning some "D3.js" and attempting to get my head around the way data is processed and selected.
I'm stuck on the following task I've created for myself.
Ideally, I want something that is functionally equivalent to:
<svg>
<circle r="20.5" cx="100" cy="200"></circle>
<circle r="20.5" cx="300" cy="10"></circle>
</svg>
What I have currently (with my logic) is:
var matrix = [ [{ "x": 100, "y": 200 }], [{ "x": 300, "y": 10 }]];
var result = d3.select("body").append("svg") // Append SVG to end of Body
.data(matrix) // select this data
.selectAll("g") //g is a svg grouping tag
.data(function (d) { return d; }) //Unwrap the first part of the array
.enter() // Grab all the data that is new to the selection in each array
.selectAll("g")
.data(function (d) { return d;}) // foreach each item inside the 1D array
.enter() // For all the data that doesn't exist already in the SVG
.append("circle") // Append Circle to the DOM with the following attributes
.attr("r", 20.5)
.attr("cx", function (d) { return d.x; })
.attr("cy", function (d) { return d.y; });
};
Weirdly enough the following :
var result = d3.select("body").append("svg")
.data(matrix)
.selectAll("g")
.enter()
.append("circle")
.attr("r", 20.5)
.attr("cx", function (d) { return d.x; })
.attr("cy", function (d) { return d.y; });
};
Seems somehow able to get the first item in the array but doesn't iterate correctly. I'm not quite sure how it's entering the array.
D3 seems to be quite a big step away from the programming paradigms I'm used to, and more difficult to debug so it would be awesome if someone could explain where I'm going wrong.
Oh, and while the example is quite useless and I could flatten it using the merge command - for the purposes of fully understanding D3 manipulation. I'd like to draw the couple of circles without the merge :)
Thanks!
Seeing you mention that you're new to d3 I'll make a few comments on the basics.
The first is that we're trying to place some svg elements on the DOM, so first we have to have a svg canvas to work on. Typically its set up early in the code and looks something like this:
var svg = d3.select("body")
.append("svg")
.attr("width", 350)
.attr("height", 250);
Note that it would be best to define variables for height and width (but I'm being lazy).
So now you have your canvas lets look at how d3 iterates. d3 iterates over an array, so you don't have to have an array within an array for your example as in:
var matrix = [ { "x": 100, "y": 200 }], [{ "x": 300, "y": 10 }];
Now you're second block of code is almost there, with just a bit of rearrangement. The first thing we need to do is t create placeholders for the circles in your svg canvas using svg.selectAll("circle"). Next we introduce the data to the empty placeholders using data(matrix) and this is bound using 'enter()`. Now all we have to do is append the circles and give them some attributes which is all the rest of the code does
svg.selectAll("circle")
.data(matrix)
.enter()
.append("circle")
.attr("r", 20.5)
.attr("cx", function (d) {
return d.x;
})
.attr("cy", function (d) {
return d.y;
});
You can see this all put together in this fiddle with some minor changes.
If you want to get to know d3 I'd really recommend get Scott Murray book on d3 it's an excellent introduction