Can I prevent chart values disappearing on the edges of x-axis of Highcharts after zooming? - reactjs

I'm using highcharts-react-official for a histogram with typescript. The problem I'm facing is, when user zooms in the values on the extreme of x-axis disappear (highlighted relevant x-axis values).
highchart
The zoom configurations that I'm using in Highcharts are something like this:
zoom on x-axis only
I did go through Highcharts documentation and some articles as well, but couldn't find any solution. If you have any previous experience in Highcharts then I'm sure you would be able to assist me here.

You are looking for cropThreshold property. From Highcharts API:
cropThreshold: number
When the series contains less points than the crop threshold, all
points are drawn, event if the points fall outside the visible plot
area at the current zoom. The advantage of drawing all points
(including markers and columns), is that animation is performed on
updates. On the other hand, when the series contains more points than
the crop threshold, the series data is cropped to only contain points
that fall within the plot area. The advantage of cropping away
invisible points is to increase performance on large series.
Defaults to 50.
You can increase the value:
plotOptions: {
series: {
cropThreshold: 9e9
}
}
Live demo: https://jsfiddle.net/BlackLabel/w6y4zdk8/
API Reference: https://api.highcharts.com/highcharts/series.column.cropThreshold

Related

React + Leaflet: how to rotate an array of markers and Rectangle vectors around (i) its center and (ii) one of its corners

I have created a very simple leaflet map displaying an array of markers as a square which I want to rotate through any angle around its center or relative to its bottom left hand vertex (which is also its origin & position[0][0]).
https://codesandbox.io/s/react-leaflet-grid-with-markers-ds9yl?file=/src/index.js
I don't wish to rotate individual markers (there's plugins for that) but the entire grid which should maintain its shape with all relative marker spacings remaining the same but with the entire map rotated through any angle. As an added complexity the each marker is rendered within a grid cell which is just a leaflet rectangle but which also needs to maintain its position relative to adjacent cells.
It would be a big bonus to be to be able to apply the transform when generating the grid, but applying the transform to the grid shown is also a great start.
Leaflet already provides path transforms but I need to transform an entire array of markers and their path representations. It looks like a geometry/maths problem but I'm hoping that leaflet already has it covered.
Any help or advice much appreciated.
Ok my friend. This was not trivial. But it was fun.
Working codesandbox
There is nothing built in to leaflet to make this happen. I am a big fan of leaflet-geometryutil to do GIS calculations and transformations in leaflet. While leaflet-path-transoform exists, I found it to be too narrow in scope for what you need. Rather, let's invent our own wheel.
The absolute simplest way to approach this is to take every coordinate that's involved, and rotate it around a given latlng. That can be done with leaflet-geometryutil's rotatePoint function. Note the documentation there is not 100% correct - it takes 4 arguments, the first being the map instance. So I had to get a ref to the map by tagging the <Map> component with a ref.
I threw a bit of UI on there so you can manually change the angle, and toggle the point of rotation from the center of the grid to the bottom left corner. That part is a bit trivial, and you can check out the code in the sandbox. The most crucial part is being able to rotate every point involved in the grid (squares and markers alike) around a rotation point. This function does that:
const rotatePoint = React.useCallback(
(point) => {
const { lat, lng } = L.GeometryUtil.rotatePoint(
mapRef.current.leafletElement,
L.latLng(point[0], point[1]),
transformation.degrees,
L.latLng(axis[0], axis[1])
);
return [lat, lng];
},
[mapRef, transformation, axis]
);
The axis parameter is the rotation origin we want to use. transoformation.degrees is simply the number from a user input to get the nuber of degrees you want to rotate. I'm not sure how you plan on implementing this (UI vs programatically), but this function enables you to rotate however you want.
When the map is created, we take your gridBottomLeft and gridSize, and calculate an initial grid, called baseGrid, and save that to state. Really this doesn't need to be a state variable, because we don't expect it to change unless gridBottomLeft or gridSize changes, in which case the component will rerender anyway. However I kept it as a state var just to keep the same logic you had. It might also make sense to keep it as a state var, because as you see, when you toggle between different rotation origins, things may not behave as you expect, and you may want to reset the baseGrid when you toggle rotation origin points.
We keep a separate state var for the current state of the grid, grid, which is a variation of the baseGrid. When the user changes the degree input, a useEffect is fired, which creates a transofmration of baseGrid based on the degree number, and sets it to the grid state var:
useEffect(() => {
const rotatedGrid = baseGrid.map((square) => {
return {
id: square.id,
positions: square.positions.map((coord) => {
return rotatePoint(coord);
}),
center: rotatePoint(square.position)
};
});
setGrid(rotatedGrid);
}, [transformation.degrees, bottomLeft, rotatePoint, baseGrid]);
As you can see, what I'm doing is applying our rotation transformation function to all points in the square (renamed to positions), as well as the marker's position (renamed center).
And voila, the entire grid rotates, along with its markers, around the axis point that you define.
**Note that you were using the Rectangle component, with 2 points as bounds to define the rectangle. This no longer works as you rotate the rectangle, so I converted it to a Polygon, with the 4 corners of the square as its positions prop.
Also note this will not work in react-leaflet version 3. v3 has an absolute ton of breaking changes (which IMO have greatly improved the performance and UX of the library), but the management of refs and changing props is completely different, and as such, will need to be accounted for in v3. If you have questions about that, comment and I can write a bit more, but this answer is already long.

Recharts: how is it possible to show only the value of ONE data point inside a Tooltip?

I am trying to implement the following example inside a Recharts LineChart: the Tooltip value is relative to the blue point, because my mouse happens to be near it, and further away from the grey point with the same x-value. If I move the mouse closer to the grey point, the tooltip content changes.
However, all available examples show that a Recharts Tooltip receives data about all the data series being drawn and that it seems not possible to discriminate the point nearest to the mouse, so that the Tooltip may provide its value only.
Is there a way to specify for which dot I want to send data to the Tooltip?
At the end of a long fruitless search, I decided to solve this problem myself.
The minimal code is published in this Github gist.
The basic problem to solve is that any standard Recharts tooltip receives information about:
the x-value where the mouse pointer is at the moment, expressed in pixels on the chart canvas
the y-values for all the data series in closest position to the mouse x-value, expressed in the y-axis real-world unit (euros, kilograms, etc.)
It is necessary therefore to feed the custom tooltip also with y-axis mouse position information expressed in pixels on the chart canvas.
The tooltip can then calculate which data series is closest to the vertical mouse position and display only the value belonging to that data series.
Extracting the y-position in pixels is tricky, because Recharts changes the mapping between pixel and ordinate values each time it redraws the chart. But there is a chart component that must know very well this mapping, in order to place itself at the right vertical position and display the corresponding real-world ordinate value: that's every tick on the y-axis.
Problem is: how do we plug into the Recharts drawing workflow in order to get to know the mapping?
Here's how: the tick property of the Recharts YAxis component allows to provide a custom React component, albeit not documented with examples.
This custom component is instantiated one time for each tick that Recharts decides to place on the y-axis.
By trial and error I found out that my custom Tick component receives the following properties:
{ x, y, payload, ...anyCustomPropertyAddedByMe }
Where x and y are the cartesian coordinates of the tick (canvas pixels) and payload is such an object:
{ coordinates, isShow, offset, tickCoord, value }
Where value is expressed in real-world y-axis units.
The idea is to find out the couple (y, value) for the lowest and highest tick in each drawing and calculate the conversion factor between pixels and real values.
This will allow the custom tooltip to perform the computations mentioned above.
(Strictly speaking it would be enough to collect two couples from the first two ticks that are instantiated at each chart repaint, but choosing the two most far apart gives more precision)
The whole algorithm is divided among three components:
a tooltipCollector: this is a JavaScript module that presents two methods:
collect(value, y), invoked by the customized tick, that stores all couples (y, value) in a private array _collection
maxAndMin(), invoked by the custom tooltip, that reads the _collection array and returns the couple of items in the collection that represent the lowest and highest ticks (watch out that vertical pixel values in a canvas are measured upside down!)
a CustomizedTick React component that:
receives the tooltip collector among its custom properties
sends its y and payload.value to the collector by invoking its collect(y, value) method
returns a very simple JSX tick markup that makes usage of y (to place itself at the right vertical position) and payload.value (to display the user the real-world value the tick indicates)
a CustomTooltip React component that:
receives the tooltip collector among its custom properties and invokes its maxAndMin() method
verifies (by considering its prop coordinate.y) whether it's close enough to one of the chart data series, using a threshold value; this ensures that the tooltip is drawn only when the mouse cursor is very close to a point on the graph
modifies its returned JSX markup to contain only the value relative to the data series the mouse is closest to; in case more points in the chart are closer than the threshold, the tooltip will present more than one value
The code in my gist has been simplified to remove all unnecessary JSX markup. It presents a chart component that puts at work all the above mentioned components.
Please note that the standard Recharts behaviour of highlighting all the data series' points to which the tooltip abscissa is pointing has not been changed. It is therefore good practice to put a color code in the tooltip content to illustrate clearly to which data series the displayed value belongs.

How to hide axis bars in area chart and line chart in Google Data Studio

I currently have this issue where I am trying to hide the Y-axis of this line chart. Currently there is only the option to hide both axes in GDS.
Issue being is that the floating number at the y axis looks awkward.
Could anyone think of a work around? maybe hiding both axes and then creating a blank chart with the date values and using that as the x axis ticks.
One workaround is to draw a Shape or line over the axis and set it to a colour that blends in with the background, (although in the case above, it would cut into the first data point and data label) using Shift + movement keys for precision placement.
Google Data Studio Report as well as a GIF to elaborate:

SSRS bar chart issue

I am trying to add one box and one line on x-axis. Please look at below bar chart.
I tried using stripline but I cannot set height for stripline. It goes till 100.
Is there any way I can do this?
Unfortunately, SSRS doesn't provide the functionality you're looking for. A stripline is the closest you can get to that, but like you said, you can't control its height. The only way you could simulate this behavior would be to use a Background Image for your stripline, but that may be more work than it's worth. It would require a lot of manual adjustment to get the image to line up on the chart.
I would add a series to the chart using the Stock chart (under Range). In the Series Properties I would set the High value to the height desired for your line (~52 in your example). Ideally this would come from a dataset value.
Set the Low, Open and Close values to 0.
Try two Stripe Lines. First, create the strip line which represents the vertical value you're after. In my case, I made one that was 50% of the graph height off of the Y-Axis.
Chart Properties:
Height of StripeLine:
Once the stripe line is the correct height for the chart, create a 'mask' stripe line along the X-axis that will cover the portion of the Y-axis line you want hidden.
Chart Propterites:
Width of Stripe Mask:
Using these methods, and some really clever expression writing, you should be able to make the line exactly as high, and as wide as you desire.

Silverlight toolkit chart too many labels on axis

I'm using the newest chart control from silverlight toolkit to plot some data. For small cases it works ok, but for bigger samples the X axis labels overlap. It would be no problem if the chart would simply omit some of the values or I could specify to just show every 10th of them ...
I couldn't find any properties providing this behavior. Any ideas?
Assuming this is a Linear axis then you can specify the interval to use via the the Interval property on the axis.
If the axis in question is Category Axis then dropping some labels may not be valuable to the user. One option is to use the LayoutTransfomer to rotate the labels to an angle reducing the width needed for each one. See this Delay Blog on the subject.

Resources