tick mark line styling with d3.js - d3.js

Is there a way to select all of the tick mark lines and make them dashed? I tried selecting all lines, but that only got me halfway there. Here's my code so far:
http://jsbin.com/zosihajari/edit?js,output
What I would do is to get hold of the vertical lines, make them grey and dashed but also if possible offset them a little off the axis line so they don't start/end at the bottom/top of the svg space. Is there a way to do that?

Set the outerTickSize to zero:
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.outerTickSize(0)
.innerTickSize(-(height-20));
Here is your JSBin: http://jsbin.com/jepudifowu/1/edit?css,js,output

Related

Modifying ticksize when resizing the chart

I am using the trick of sizing the ticks on my axes in order to render a grid effect on my chart. The problem I have is that I am not able to work out how to resize the ticks on my y axis when the width of the chart changes due to a window resize.
The code that I have to initialize my chart is as follows:
this._xRange = d3.time.scale().range([0, chartWidth]);
this._yRange = d3.scale.linear().range([chartHeight, 0]);
this._xAxis = d3.svg.axis().scale(this._xRange)
.orient("bottom")
.tickSize(-chartHeight)
.tickSubdivide(true);
this._yAxis = d3.svg.axis().scale(this._yRange)
.orient("left")
.tickSize(-chartWidth)
.tickSubdivide(true);
When the chart is resized, I am recalculating the width and height of the chart and attempting to redraw the axes. For the y axis I am using the following code:
// Redraw the y axis
this._yAxis = d3.svg.axis().scale(this._yRange)
.orient("left")
.tickSize(-chartWidth)
.tickSubdivide(true);
this._chart.call(this._yAxis.orient("left"));
This is failing with the following exception in the browser console:
DOMException: Failed to execute 'insertBefore' on 'Node': The node before
which the new node is to be inserted is not a child of this node. "Error:
Failed to execute 'insertBefore' on 'Node': The node before which the new
node is to be inserted is not a child of this node.
I believe that I have hit upon a solution. It appears that I need to remove the existing y axis, create a new generator and then add the new generator to the chart. I am using the following code to do this:
d3.select(".y.ResourceStatsAxis").remove();
this._yAxis = d3.svg.axis().scale(this._yRange)
.orient("left")
.tickSize(-chartWidth)
.tickSubdivide(true);
this._chart.append("g")
.attr("class", "y ResourceStatsAxis")
.call(this._yAxis);

NVD3.js multiChart x-axis labels is aligned to lines, but not bars

I am using NVD3.js multiChart to show multiple lines and bars in the chart. All is working fine, but the x-axis labels is aligned only to the line points, not bars. I want to correctly align labels directly below the bars as it should. But I get this:
With red lines I marked where the labels should be.
I made jsFiddle: http://jsfiddle.net/n2hfN/
Thanks!
As #Miichi mentioned, this is a bug in nvd3...
I'm surprised that they have a TODO to "figure out why the value appears to be shifted" because it's pretty obvious... The bars use an ordinal scale with .rangeBands() and the line uses a linear scale, and the two scales are never made to relate to one another, except in that they share the same endpoints.
One solution would be to take the ordinal scale from the bars, and simply adjust it by half of the bar width to make the line's x-scale. That would put the line points in the center of the bars. I imagine that something similar is done in the nv.models.linePlusBarChart that #LarsKotthoff mentioned.
Basically, your line's x-scale would look something like this:
var xScaleLine = function(d) {
var offset = xScaleBars.rangeBand() / 2;
return xScaleBars(d) + offset;
};
...where xScaleBars is the x-scale used for the bar portion of the chart.
By combing through the source code for nvd3, it seems that this scale is accessible as chart.bars1.scale().
Maybe someday the authors of nvd3 will decide that their kludge of a library deserves some documentation. For now, I can show you the kind of thing that would solve the problem, by making a custom chart, and showing how the two scales would relate.
First, I'll use your data, but separate the line and bar data into two arrays:
var barData = [
{"x":0,"y":6500},
{"x":1,"y":8600},
{"x":2,"y":17200},
{"x":3,"y":15597},
{"x":4,"y":8600},
{"x":5,"y":814}
];
var lineData = [
{"x":0,"y":2},
{"x":1,"y":2},
{"x":2,"y":4},
{"x":3,"y":6},
{"x":4,"y":2},
{"x":5,"y":5}
];
Then set up the scales for the bars. For the x-scale, I'll use an ordinal scale and rangeRoundBands with the default group spacing for nvd3's multiBar which is 0.1. For the y-scale I'll use a regular linear scale, using .nice() so that the scale doesn't end on an awkward value as it does by default in nvd3. Having some space above the largest value gives you some context, which is "nice" to have when trying to interpret a chart.
var xScaleBars = d3.scale.ordinal()
.domain(d3.range(barData.length))
.rangeRoundBands([0, w], 0.1);
var yScaleBars = d3.scale.linear()
.domain([0, d3.max(barData, function(d) {return d.y;})])
.range([h, 0])
.nice(10);
Now here's the important part. For the line's x-scale, don't make a separate scale, but just make it a function of the bars' x-scale:
var xScaleLine = function(d) {
var offset = xScaleBars.rangeBand() / 2;
return xScaleBars(d) + offset;
};
Here's the complete example as a JSBin. I've tried to document the major sections with comments so it's easy to follow the overall logic of it. If you can figure out from the nvd3 source code exactly what each of the elements of the multiChart are called and how to set the individual scales of the constituent parts, then you might be able to just plug in the new scale.
My feeling on it is that you need to have a pretty good handle on how d3 works to do anything useful with nvd3, and if you want to customize it, you're probably better off just rolling your own chart. That way you have complete knowledge and control of what the element classes and variable names of the parts of your chart are, and can do whatever you want with them. If nvd3 ever gets proper documentation, maybe this will become a simple fix. Good luck, and I hope this at least helps you get started.

D3 Redraw Y-axes dynamically

I would like to create a dynamic graph with multiple (linear) axes. After the axes have been drawn, I would like (as new data arrives) to change the Data Domain and redraw/update the axes. Can I select the existing axis with D3 and do this or do I have to explicitly save each axis in my code? I hope my question is not confusing.
// init all Y-Axis
$.each(chart.YAxes, function (index) {
var yScale, yAxis;
yScale = d3.scale.linear().range([chartHeight, 0]);
yScale.domain([this.YMin, this.YMax]);
yAxis = d3.svg.axis()
.scale(yScale)
.ticks(10, this.Title)
.orient("left");
d3Chart.append("g")
.attr("class", "yAxis " + "y" + this.ID)
.call(yAxis);
......
// update Y-Axis (after new data arrives...)
var myYAxis = d3.select(".y" + yAxis.ID);
var myScale = myYAxis. **// get Scale ??**
myScale.domain([newYMin, newYMax]);
d3Chart.select(".y" + yAxis.ID)
.transition().duration(300).ease("sin-in-out")
.call(myYAxis);
thx...!
You need to keep references to the axis object so that you can call it again. Selecting the DOM element that contains it and calling that won't work. There are lots of examples on how to update axes, e.g. in this question.

D3.js: Hide the last tick on an axis?

I am using D3.js to draw an axis with ticks. I would like to hide only the last tick on the y-axis.
Maybe a picture will make it clearer. This is what my axis looks like at the moment - I'd like to hide the "21" and its associated tick.
Here is my current code:
var yAxisScale = d3.svg.axis().orient("left");
yAxisScale.scale(y_position);
yAxisScale.ticks(20).tickFormat(function(d) { return d+1; });
var yAxis = vis.selectAll("g.y.axis").data([1]);
Is there a way I can hide only the last tick, regardless of how many ticks there are on the y-axis?
I tried adding this line, but it doesn't work, even though the selectAll expression appears to return the right element.
d3.select(d3.selectAll("g.y.axis g")[0].pop()).style('opacity', 1e-6);
The opacity is still set to 1.
you should to take a look at axis.tickSize(). it allows you to set the size of the major, minor, and end ticks.
also see here for similar question:
Remove end-ticks from D3.js axis

Highstock : Yaxis last horizontal label value not showing

Im having an highStock chart that is not displaying the last yAxis horizontal line value.
Let's take a look on the picture as it shows the problem: It shows 299, 400, 600 but the last one is not displayed
http://s10.postimg.org/rlp7via7t/highstock.png
You should set showLastLabel as true http://api.highcharts.com/highstock#yAxis.showLastLabel

Resources