Recharts - How to preserve edge value of Y-Axis? - d3.js

I have a chart with proper display of data, but my Y-Axis is linear (should be) and it crops data (see screenshot).
I expect Y-Axis to show linear data AND respect the edge (max) value of the chart.
I was trying to work with d3-scale but I failed - don't know how to "append" max value to the scale. The only way I figured is to manually calculate all the ticks which I'd like to avoid.
My Y-Axis code is
<YAxis
domain={[data.yAxis.min, data.yAxis.max]}
scale="linear"
tickFormatter={formatEnergyAxis}
/>
Where min is 0 and max is 3200 (unit conversion happens in formatters).
Is there a way to adjust the scale?

If possible, call the function .nice() inside YAxis. Otherwise, call it before passing the values to the binding:
d3.scaleLinear().domain([0, 3200]).nice().domain()
// [0, 3500]
That would be
<YAxis
domain={d3.domain([data.yAxis.min, data.yAxis.max]).nice().domain()}
scale="linear"
tickFormatter={formatEnergyAxis}
/>

On your Y-Axis, you can specify your last tick to be visible with the props interval set to preserveEnd, like this:
<YAxis
domain={[data.yAxis.min, data.yAxis.max]}
scale="linear"
tickFormatter={formatEnergyAxis}
interval="preserveEnd"
/>
You can also use the value preserveStartEnd to be have the root & edge values visible.

Related

Recharts square zoom implementation

The sample I am talkin' about is here
https://recharts.org/en-US/examples/HighlightAndZoomLineChart
and here
https://codesandbox.io/s/highlight-zomm-line-chart-v77bt
Please press left button of the mouse and drag it to the right - this is how zoom is currently done. Please take a look at the activeLabel variable.
Currently recharts could make a zoom into the graph by passing the x coordinate (which is stored in activeLabel variable) and zooom looks like a pillar all over the y coordinate.
I want to select an area - square or rectangle to make more customized zoom. The trouble is that I can't get the y value of the graph (not pixel in window). Recharts gives only x coordinate of the graph, but not y.
I've searched all over the issues on gitHub, mailed the creator with no luck.
I've read the
Recharts value at pointer to show in tooltip?
but I could not get how could I count the initial values of chartX and chartY in my responsive container, so it is very depends on the window user has.
Please help me to find a solution to match chartY in pixels to my real values in my chart depending on Responsive Container I am using.
Zoom can be done by using the mouse events of the chart.
You can store the values in a state then call the zoom function on onMouseUp.
And in zoom function, you can set the domains of the axes.
Don't forget to set the axes to allowDataOverflow.
And you can also draw the rectangle by using ReferenceArea
function zoom () {
setXAxisBoundaries([rectangle[0], rectangle[1]])
setYAxisBoundaries([rectangle[2], rectangle[3]])
}
<ScatterChart
onMouseDown={(event) => setRectangle([event.xValue, event.yValue])}
onMouseMove={(event) => setRectangle(rectangle => [...rectangle, event.xValue, event.yValue]))}
onMouseUp={zoom}>
<XAxis
dataKey="x"
allowDataOverflow
domain={xAxisBoundaries}
type="number" />
<YAxis
dataKey="y"
allowDataOverflow
domain={yAxisBoundaries}
type="number" />

tick axis getting out of svg barchart

I am trying to do a barchart with Recharts but ticks on both axis are getting out of svg:
Do you know to solve this ?
In your example, your tick labels have an angle that puts them out of the svg zone. To turn back your tick labels like on a line, you need to either update the angle prop to 0, like the following:
<XAxis dataKey="name" angle={0} />
Removing the angle prop from the XAxis would work as well, since its default value is 0.

NVD3 X axis incorrect ordering (dates)

I'm trying to visualize 2 series but when I visualize them together, the dates don't go in sequential order anymore.
Here is the fiddle: http://jsfiddle.net/hohenheim/6R7mu/21/ Notice the weird x-axis.
Is there a way to fix the x axis on nvd3?
The data looks like this:
data1 = [{
"date": 1396828800,
"impressions": 49145385
}, {
"date": 1396915200,
"impressions": 46704447
} ....
The NVD3 "multiBarChart" uses an ordinal (category) scale, so it will only display the x-values you give it, in the order in which they are added to the scale. Because your two series only partially overlap on the x axis that's causing problems.
Unlike other NVD3 chart types, the multiBarChart doesn't give you the option of setting your own scale -- it needs to use an ordinal scale in order to generate even widths for the bars. However, you can set the x domain (the list of categories to use for each bar), by calling chart.xDomain(arrayOfXValues).
The array will need to be an ordered array of Date values that spans your data. In order to generate it, you'll need the d3 time intervals range functions. You might also need the d3.extent function to find your max and min values.

d3 autospace overlapping tick labels

Is there a way in d3 to not draw overlapping tick labels? For example, if I have a bar chart, but the bars are only 5 pixels wide and the labels are 10 pixels wide, I end up with a cluttered mess. I'm currently working on an implementation to only draw the labels when they do not overlap. I can't find any existing way to do that, but wasn't sure if anyone else had dealt with this problem.
There is no way of doing this automatically in D3. You can set the number of ticks or the tick values explicitly (see the documentation), but you'll have to figure out the respective numbers/values yourself. Another option would be to rotate the labels such that there is less chance of them overlapping.
Alternatively, like suggested in the other answer, you could try using a force layout to place the labels. To clarify, you would use the force layout on the labels only -- this is completely independent of the type of chart. I have done this in this example, which is slightly more relevant than the one linked in the other answer.
Note that if you go with the force layout solution, you don't have to animate the position of the labels. You could simply compute the force layout until it converges and then plot the labels.
I've had a similar problem with multiple (sub-)axis, where the last tick overlaps my vertical axis in some situations (depending on the screen width), so I've just wrote a little function that compares the position of the end of the text label with the position of the next axis. This code is very specific to my use case, but could adapted easily to your needs:
var $svg = $('#svg');
// get the last tick of each of my sub-axis
$('.tick-axis').find('.tick:last-of-type').each(function() {
// get position of the end of this text field
var endOfTextField = $(this).offset().left + $(this).find('text').width();
// get the next vertical axis
var $nextAxis = $('line[data-axis="' + $(this).closest('.tick-axis').attr('data-axis') + '"]');
// there is no axis on the very right, so just use the svg width
var positionOfAxis = ($nextAxis.length > 0) ? $nextAxis.offset().left : $svg.offset().left + $svg.width();
// hide the ugly ones!
if (endOfTextField > positionOfAxis) {
$(this).attr('class', 'tick hide');
}
});
The ticks with color: aqua are the hidden ones:

Viewing Part of a figure

I made a simulation of 10000 times and want to view part of simulation between 5000-5200. I am able to view it with the code below, but the x-axis says 0-250. I want the x-axis to display the exact figure of 5000-5200. Also there seems to be a small gap at the end of the figure as the axis runs up to 250 for some reason. I just want to view the figure in for this set time with the x-axis showing the exact labels and without the gap at the end.
Thanks
N=10000;%Number of simulation
P=0.02;
Q = zeros(N,1); %current value of queue
X=zeros(N,1);%simulation data
Ci=0;
L=0.9;
Bu=zeros(N,1);
Bs=30;
Bd1=50;
Bd2=270;
Ti=0;
for Ti=2:N
U=rand(1);
a=log10(U);
b=log10(1-P);
c=(a/b);
d=1+c;
X(Ti)=round(d);
Ci=Ci+1;
if X(Ti)< (L)*(Bs)
Bu(Ti)=Bs;
else if X(Ti) < (L)*(Bs+Bd1)
Bu(Ti)=Bs+Bd1;
else
Bu(Ti)=Bs+Bd1+Bd2;
end
end
Ti=Ti+1;
end
plot(X(5000:5200,1),'r');
set (gca,'ylim',[0 400]);
hold on;
plot(Bu(5000:5200,1),'b');
set (gca,'ylim',[0 400]);
hold off
Plot expects two inputs, the first depicting the horizontal axis and the second depicting the vertical axis. When you do not supply two inputs, then it computes the length of the single input (in this case that length is 5200-5000 = 200), and it just uses 1 through that length (1:200 in this case) as if it is the values for the horizontal axis variable.
I think you want to issue the command:
plot(5000:5200, X(5000:5200,1), 'r')
Often Matlab will adjust plot axes for better default views, so it's probably showing the axis out to the index 250 just by virtue of some default plotting convention. You can similarly use set(gca, 'xlim', [5000 5200]) if you wish.

Resources