Wrong number of lines/ticks on d3 bar chart - javascript

I have a simple d3 bar chart and I'm trying to draw horizontal lines in the background.
The bars on the chart represent percentages, with a full-height bar being 100%. I want to show 4 bars, at 25%, 50%, 75% and 100% levels. But if I do this:
svg.selectAll('.rule')
.data(y.ticks(4))
.enter().append('line')
.attr('class', 'rule')
.attr('x1', 0)
.attr('x2', width)
.attr('y1', y)
.attr('y2', y);
then the y.ticks(4) shows 5 lines. If I change it to 3 I get 2 lines. If I change it to 5 then I still get 5 lines. Here's an example on JSFiddle.
Also, at the end of that script, I tried adding a y-axis, but it only displays horizontally - how do I get it to appear vertically? This seems to Just Work in all the examples I've seen.

The param of the ticks() method of d3.scale.linear() is just a hint. The method uses this as an approximation, but it will pick "pretty" values. (see here: https://github.com/mbostock/d3/wiki/Quantitative-Scales#wiki-linear_ticks)
If you want to set the values explicitly, you need to instantiate a d3.svg.axis() and use axis.tickValues() (like you did further down).
Regarding your 2nd question. The axis has a default orientation (which you're seeing), for using as a horizontal, X axis. You need to call .orient("left") or .orient("right") to get a vertical axis. Note, if you use "left" orientation, you won't actually see an axis, bc its numbers will run off the left edge of the SVG and get cropped. So it's a good idea in general to add some padding to the SVG and shift all your graphics within it. If you use "right" orientation you'll see the numbers, but typically in this case you'd translate the axis to the right side of the graph.

Related

D3 radial bar chart adjust radius scaling

If one examines this block:
https://bl.ocks.org/mbostock/8d2112a115ad95f4a6848001389182fb
The gridlines are in increments of 20. However the radius of each gridline does not appear to be equal as it scales up:
I'm guessing there is some geometric justification for this, but that's not what I'm after for my chart. I only want aesthetics, I need the gridline circles to be equidistant from each other.
Question
Using Bostock's radial scale script as seen in the above block, is there any way to adjust the scaling of the radii? I want the scaling to be equidistant.
The only thing you need is to change this...
var y = d3.scaleRadial()
... for this:
var y = d3.scaleLinear()
Here is the bl.ocks with that change only: https://bl.ocks.org/GerardoFurtado/0a0b22d15c4e715e4c748335e37330fb/1670bbcdfdcbed6b6a0ae2a56d5f153570d969d1
PS: There is indeed a geometrical explanation for this: a circle with radius 2r has an area four times bigger than a circle with a radius r. That's why we always (at least in truthful charts) scale the circle's radius to the square root of the encoded datum. Well, you mentioned that "I only want aesthetics". As a data visualisation specialist/enthusiast who happens to be a D3 programmer, not the other way around, I suggest you reconsider your approach and keep the radial scale. Charts that prioritise aesthetics over information are normally bad charts, and charts that impose aesthetics ignoring information are simply untruthful charts.

Chart bars not aligning with x axis values in d3.js

Trying to learn and implement d3.js for the first time.
In the fiddle, we needed to reduce the width of each bar from
.attr('width', xScale.rangeBand()) line 46
to
.attr('width', '10') line 50
When doing so, the horizontal x axis labels are getting dis-aligned with vertical bars which is not needed.
Tried to see a few solutions:
We're unable to see tickValues anywhere in my code.
Unable to understand where to put SVG-Text
We do not wish to hide the x axis labels
Ours is numeric, they're discussing about date time kind of axis
Any suggestions, kind folks?
Try this code:
.rangeBands([0, width], someValue)

D3 - align leftmost side of circle to x-axis time scale

I'm trying to make a timeline where the:
circle radius = visit duration
x-position = time of visit
.attr('cx', function(d,i) { /* insert code here */ } )
basically what I want is tell d3 to align the circle to "startDate", however there's a problem with this as circles with bigger radii will shift towards the left, making it look inaccurate since it's aligned to the center.
what are possible solutions for this?
here's the code: http://jsfiddle.net/jg4v1ymx/2/
edit - instead of the radius: if data is bigger, tell d3 to increase circle size by diameter? the problem is I don't want big radii circles overlap with circles in nearby dates
You just need to pass the x scale the date, as in:
.attr('cx', function(d,i) {
return x(d.date);
} )
You also need to make sure that you have set the domain before you do this, so move the x.domain(/*stuff*/) above the chart1 line.
You can see a working fiddle

transition of x-axis results in overflow

First of all, no: this question is not about the (yet) ugly transition of the lines (I might open another one for that, though..).
I'm displaying data in line charts and the user can select the time horizon. The x-axis then correspondingly transitions so as to fit to the changed time horizon. In attached image, e.g., the time horizon was 1 week and then I switched to 4 weeks. The number of ticks on the x-axis increases from 7 to 28, correspondingly.
Question: How can I prevent the x-axis animation to display outside the svg container? As you can see, the additional dates fly in from the left and they are being animated far far outside the container.
Any ideas?
Right now, the transition works probably in the most simple way it could:
// format for x-axis
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickFormat(d3.time.format("%d.%m"))
.ticks(d3.time.days, 1)
.tickSubdivide(0);
// Update x-axis
svg.select(".x")
.transition()
.duration(500)
.call(xAxis);
It could work if you set CSS rule
overflow:hidden
for part of page which contains the chart.

D3 time axis - why do tick marks seem to be invisible by default?

I'm working on a pretty regular graph using an X time axis.
The axis code is pretty standard:
var xScale = d3.time.scale()
.domain([tlState.startdate.getTime(), tlState.enddate.getTime()])
.range([0, width]);
var xHourAxis = d3.svg.axis()
.scale(xScale)
.ticks(d3.time.hours, 6)
.tickFormat(d3.time.format("%_Hh"))
.tickSize(5,1)
.orient('bottom');
root.append('g')
.attr('class', 'axis')
.attr("transform", "translate(" + 0 + "," + height + ")")
.call(xHourAxis);
The tsState.* functions simply return starting/ending dates for the axis.
My problem: the axis tick label are visible, but I can't see the tick marks. They are clearly there in the DOM tree (<line y2="5" x2="0"></line>), but they only become invisible when I explicitly set their "stroke" attribute to something non-white.
I could easily solve this using CSS to set the stroke on tickmarks... But why are they invisible in the first place? I've googled around, but have found nothing indicating a default stroke color for tick marks...
Thanks a lot for any hints,
wwwald
According to the SVG spec, the default value for stroke is none. Since d3 uses a path for the ticks, which only show a stroke and no fill, nothing shows up until you style them.
I'm not sure why they decided on that; maybe to make adding a border to shapes a little simpler. Since stroke-width defaults to 1, adding a border only requires changing one attribute. If stroke was any other value besides none, stroke-width would have to default to 0 (don't want to give text a stroke by default!), and it would be a little counter intuitive to set up strokes for the first time: you'd have to know to change stroke-width to a positive number before seeing any strokes.
Why doesn't d3 fix this problem for us? d3's axis is built on top of SVGs and in general d3 lets you work very closely with the standards it is built on top of (css/html/svg). This makes it possible to push the medium to its limits, but also means you run into these issues occasionally.

Categories