update clipPath alongside a dynamic yaxis in d3js - javascript

I've made this (SOLVED) chart and I can't figure out how to update clipPath.
I've commented out
y.domain(d3.extent(data, function(d) { return d[city]; }));
in the change function because it didn't update the clipPath alongside the yAxis, I've tried to assign a class to the clipPath and update the y and height attribute in the change function but nothing seem to work.
Would greatly appreciate if anyone knows what I'm doing wrong or why it's not possible to update clipPath.

You set the new domain, but you also need to update those things based on the domain (both clip-paths and the area's y0):
y.domain(d3.extent(data, function(d) { return d[city]; })); // fix clipPath
svg.select('#clip-below>rect')
.attr("y", y(1))
.attr("height", height - y(1));
svg.select('#clip-above>rect')
.attr("height", y(1));
area.y0(y(1));
Here's an updated bl.ocks.

Related

Re-sizing circle SVG in D3

I'm trying to change the size of dots on a map in D3. Basically, just want to re-size the circle SVG in D3. I just want all the circles to be smaller, not trying to create proportional symbols. Here's my circles:
var centroid = map.selectAll(".centroid")
.data(centroid.features)
.enter()
.append("path")
.attr("d",path)
.attr("r", 100)
.attr("class", function(d){
return "centroid "+d.properties.info_city;
})
It's not working. I know that I can't do this in CSS, any thoughts on how to accomplish this in javascript as I'm trying to do? Thanks all!
Take a look at this plunker and let's move on from there: http://plnkr.co/edit/lKtCBKFS764MThajrqxX?p=preview
This map has similar centroids like yours. These are defined in:
g.selectAll(".centroid").data(centroids)
.enter().append("circle")
.attr("class", "centroid")
.attr("fill", fill)
.attr("stroke", stroke)
.attr("stroke-width", strokeWidth)
.attr("r", radius)
.attr("cx", function (d){ return d[0]; })
.attr("cy", function (d){ return d[1]; });
By changing .attr("r", radius) line (which is 6 in the config) to .attr("r", 2) you will get smaller circles
Here's the changed one: http://plnkr.co/edit/JUpMlnhZvZNacAIzI502?p=preview
I think you are trying to change the wrong part of the code since you should change the "r" of the circle elements not the "path" element ( I don't think path element even has a "r" attribute).
If your circles are drawn by a path then you must change the algorithm that draws those circles.
You are using the centroid coordinates to append a path as if it was a circle. This is not usual, the most common choice would be using a SVG circle, but it's OK... actually, Bostock does the same here.
The only problem is, as these are paths, not circles, changing the radius (r) will have no effect. So, to change the size of these "circles", this is what you have to do: find your d3.geo.path and add pointRadius to it.
var path = d3.geo.path()
.projection(projection)
.pointRadius(someValue);
Where someValue is, of course, some numeric value that fits your needs.
PS: for this to work properly, the types in your TopoJSON have to be "Point" or "MultiPoint".

Issue with overlapping toolitp d3.js

I found this is a very helpful example to create tooltip on line charts. I am following this to work on a line chart now. The difference is the tooltip in my chart has a box/background to contain the value showing in the tooltip, so I add append('rect') with attr('fill', 'white').
mousePerLine.append('rect').
attr('width', '38px').
attr('height', '20px').
attr('class', 'tooltipRect').
style('fill', 'white').
attr('transform', 'translate(5,-13)');
To avoid overlapping of text as well as rect, I changed line 292 according to a post here How to select multiple selectors with selectAll?
.select("text")
.attr("transform", function(d,i) {
return "translate (10,"+(3+ypos[i].off)+")";
})
to
.selectAll(".tooltipRect, text")
.attr("transform", function(d,i) {
return "translate (10,"+(3+ypos[i].off)+")";
})
Here's a fiddle of the problem.
However, the tooltips are still overlapping. Can anyone help to figure out what is the cause of the problem? Thanks in advance!
The rects keep overlapping likely because the way you are selecting them.
Why not close the selectiona at the text (keep the text selection above as is) but a make a new selection for the rect:
d3.selectAll(".mouse-per-line")
.select("rect")
.attr("transform", function(d,i) {
return "translate (5,"+(ypos[i].off - 13)+")";
});
This works for me.
I did the translation based on your initial set up of the rect. I adjusted the offset on line 286 from 15 to 20 - it looks a bit better.

why doesn't my chart update?

I can't work out why my chart doesn't update when I change selection.
Here's my code so far on Plunker
The code that seemingly doesn't work is:
dropDown.on("change", function() {
d3.selectAll("circle")
.data(orgData[this.value])
.attr("y", function(d) {
return height - price_scale(d.value);
})
.attr("height", function(d) {
return price_scale(d.value);
});
});
The code comes from the answer to a previous query that I made:
How to use d3 filter and update function to toggle between data selections
That code worked because the update function tweaked the parameters of a circle svg object. Is there a parameter I've not factored in with rect objects?
circle elements don't have height or y attributes, they have cx, cy and r attributes.
Alternatively maybe you meant to select rect elements which do have height and y attributes.

Unable to get drop-shadow on the bars

I am working on a bar chart and I need to get the chart to look like this:
Here is what I tried:
.attr("id", "drop-shadow")
.attr("height", "130%");
but it did not work.
jsfiddle
How do I fix this?
Try this fiddle.
Chart looks like that same as the image.
But i didn't do it adding a drop shadow.
Added ellipse before the bar being created and that gives the same effect as above.
svg.selectAll(".ellipse")
.data(data)
.enter()
.append("ellipse")
.attr("cx", function(d) { return x(d.age) + 30; })
.attr("cy", function(d) { return y(0); })
.attr("rx", 35)
.attr("ry", 5)
.style("fill", function(d) { return d.color2; })
This is very simple. You need to create a ellipse before the bar is created.
When we position the ellipse it acts like a drop shadow.
Sorry that i don't have time to get the contrasting colors of the bar. But you can amend it of course.
If you'd like to do it with a drop shadow.
Here's a link that requires a javascript library for the drop shadow of the svg elements.
Hope this helps.

D3 - force layout, circle within circle

In the process of learning D3.js.
Is it possible using a force layout to place a circle within another circle shape as per the picture. I am hoping to transition between a single circle per node to a display showing two circles per node. The size of the effective donut is used to illustrate another variable in the data.
Is this possible?
You don't even need to use anything other than a basic svg circle, as you find in most examples. Just bind the data to it, apply a stroke, and set the stroke-width attr to your other variable. Or r - otherVar, I'm sure you can figure that part out.
If this doesn't satisfy, build your own shape. The 'g' svg element is a container element, and lets you build whatever you like. Add two circles to a g, fill them how you like. Make sure to add them in the right order, since svg has no concept of 'on top', things just get painted in the order that you add them.
edit: okay, quick demo so you can learn some syntax. I didn't add any comments but hopefully the code is very verbose and straightforward. Find it here.
d3/svg is something that you have to just bash your head against for a while. I highly recommend spending some time creating a sandbox environment where you can quickly test new things, save, refresh browser to see results. Minimizing that turnaround time is key.
Thanks to roippi I was able to create a group containing two circle shapes.
var nodeCircles = svg.selectAll("g")
.data(nodes);
// Outer circle
var outer = nodeCircles
.enter()
.append("circle")
.attr("class", "node_circle")
.attr("r", function(d) { return d.radius_plus; })
.style("fill", function(d) { return d.color_plus; })
.style("opacity", 0);
// Inner circle
var inner = nodeCircles
.enter()
.append("circle")
.attr("class", "node_circle")
.attr("r", function(d) { return d.radius; })
.style("fill", function(d) { return d.color; })
.style("stroke", function(d) { return d3.rgb(d.color).darker(2); })
.on("mouseover", mouseOver)
.on("mouseout", mouseOut)
.call(force.drag);
Outer circle visibility is toggled via a button.
As mentioned, I use a desktop based IDE to run/test visualisation languages. Currently the IDE supports studies written in D3.js, Raphael, Processin.js, Paper.js and Dygraphs. Picture below...

Categories