Open Amnesthesia opened 6 years ago
The "stacked" charts are indeed in need of some more love. Their complex data structure make things a lot harder to calculate. I'll see what I can do 👍
Out of curiosity, what types of decorators would you like to render?
Well, I've had a couple of different issues I'm trying to work around — one is that making "timeline" charts, e.g data following a time axis, can be challenging since the points are spaced evenly, but I've worked around this by providing values with everything 0 for e.g missing minutes; but what I'm doing that requires decorators is making it possible to click the graph and drag a finger to show the values in a little pop-up.
This is especially difficult when you have two charts on top of one another, and I've solved this (in a not-so-nice way) by having a decorator child that receives all datapoints and finds their X/Y position, so that a parent pan-responder can pass down what coordinates the finger is currently on, and the decorator can check what datapoint is closest to those coordinates, and render a line and a dot with a box showing the values at that specific point.
Currently I'm doing this with AreaChart and LineChart, because StackedAreaChart gets different props and I couldn't get this working with StackedAreaChart.
I feel like having a timeline chart where the position is decided by timestamp (rather than index in the list) and its relative position to the first / last timestamp would be an amazing addition to this library; and maybe a better way to dealing with PanResponders to show decorators only when the user is clicking anywhere near them.
For now, this works, but it doesn't work at all with StackedAreaChart
Thank you for the elaborate explanation.
First of all, the spacing of your data points in different scale than linear is supported by passing in a different xScale
, check this example.
Regarding the PanResponder I think you've landed in an "ok" way of doing it. I myself did something similar but haven't since had the need for a PanResponder and as such haven't worked on it's support either.
I think I might be able to extend the variable x scale to the stacked charts as well, I'll give it a go as soon as I can. Not sure it will solve your problem though, but might bring us a step closer
I'm actually also interested in decorators for stacked charts I believe, unless there is an easier way of doing what I'd like to do.
I want to display a small tooltip with the value of a section of the graph when a user clicks that section. You could also imagine being able to overlay the number value of each section of the stacked bar graph over the sections.
This seems to also be a problem for AreaChart
if you use AreaChart
with an array of objects and a yAccessor / xAccessor (e.g for using scaleTime). When the array isn't just numbers, the x()
function provided to Decorator children doesn't work very well anymore
The x
function is the same as the one used by the chart, i.e it's supposed to be fed the value returned by xAccessor
, not the complex object
Yeah, sorry about that. After some time I realised the x function in the decorator needed a Date
object when using scaleTime
Well there you go 👍 So is this issue ready to be closed?
@JesperLekland That's up to you :-) Do StackedAreaCharts support decorators now?
I'd like to discuss usage of decorators with PanResponders and what the best practice for this is, especially if you have multiple overlaying charts (which turns out to be really messy) - can I open a new issue for a general discussion on best-practice for decorator use cases, or does that belong somewhere else?
@JesperLekland I still have my question from above, I'd like to display a tooltip above the different sections of a StackedBarGraph. It appears from the documentation that this isn't currently supported?
Well they do support decorators but they're perhaps not as intuitive as for the other charts. You have to stack the values yourself in order to get the right y
value but the x
function should work exactly the same as for other graphs. I might be able to create some examples for the examples repository that incorporate decorators for a stacked chart, it won't be highly prioritised though.
Regarding the pan-responder I think that's better suited for a separate issue.
@vjsingh What you're trying to do is supported, albeit tricky. What in the documentation makes you think it isn't? Look through the examples (specifically the one with a tooltip), check the source code and if you're still at a loss, open a new issue detailing your problem.
@JesperLekland I thought so because the "data" prop isn't passed to the children of the stacked charts, i.e.:
This chart does not call a child with the data argument. This is due to the fact that a lot of calculations go into creating the stacked chart, meaning that the original data prop doesn't provide especially valuable information when trying to layout decorators. It does however call with the rest of the common arguments
Without access to the data array, do I write decorators with just the x and y functions, and maybe my own data array passed in from elsewhere?
You render the child yourself, just pass in the data prop to it.
<Chart data={data} >
<Child data={data} />
</Chart>
But I hear you, it's not the same as for the other charts. I could of course add it but not sure it would do any difference?
One of the difficulties with decorators right now — pan responders aside — is when you have charts stacked on top of each other, meaning you have two very different datasets.
In one of my charts, I'm plotting a change over time in value, and on top of that chart, I have a LineChart
to plot a change over time in another value, to let you see how two values correlate on a timeline.
This means the charts are siblings, and have to be positioned absolutely or offset to be on top of each-other, but it also means that the Decorator
needs to be a child of one of the charts, and will only receive the x()
and y()
function of that chart. Retrieving a dataset from that chart works fine, but when you then want to find out what y
value is plotted on that x
coordinate in the sibling chart, it gets way more complicated.
I've solved this but the solution is very messy — I think StackedAreaChart
uses a static function that you can use manually to calculate the value positions if I'm not mistaken, and I'm wondering if it would be a possibility for a similar solution for other charts as well
But if you have two charts on top of each other then they should share the same domain and extent (min/max for both axes), otherwise they won't make any sense, meaning that their x()
and y()
should be exactly the same.
Could you provide a specific use case when this isn't true? (it should be for the one above).
As I said in the comment earlier you can easily pass in extra props to your decorator e.g
....
<Decorator data2={data2}/>
...
Would give you access to both datasets. Allowing you to easily retrieve the value of the opposite dataset, e.g data2[indexfoo]
They share the same X-axis, e.g displaying data for the same month, but they have completely different X-axis, e.g if one shows percentage 0-100 and the other one shows arbitrary values 0-15000, so the X-function will be the same, but not Y
I made a pull request for my example here: https://github.com/JesperLekland/react-native-svg-charts/pull/175
(It's a stacked bar chart with labels)
@JesperLekland The code wasn't too bad, but maybe some of this functionality could move into StackedBarChart to make a little easier / more intuitive?
@Amnesthesia hmm.. I see. How would you expect a chart like that to behave? I can't visualise it, could you possibly make a snack That better explains showcases your problem?
@JesperLekland Sorry, spent some time trying to get a snack working but my laptop just kept crashing :(
But a typical example would be trying to implement any of these charts for example: http://www.tylervigen.com/spurious-correlations
Ideally, I would like if charts would accept the same props but as an array, imagine e.g:
<AreaChart
series={[{
name: 'Films Nicholas cage appeared in',
data: [ // current data prop],
xAccessor: ({ item }) => item.value,
yAccessor: ({ item }) => item.timestamp,
},{
name: 'Number of people who died by falling into pools',
data: [ // current data prop],
xAccessor: ({ item }) => item.count,
yAccessor: ({ item }) => item.timestamp,
}]}
>
{ /* Decorator could receive data prop as an array and identify it by e.g name, order, etc and each item would have its own x/y function */}
<Decorator />
</AreaChart>
In an even more ideal world, that could just be Chart
and the items could accept a type
setting for line
, area
, or bar
, but that's unrelated to this I suppose.
Bottomline is, as it is now, it's very very difficult to do correlation charts, and it does feel a little bit hacky to have to overlay two charts and position them absolutely or with negative margins to show them together — it would be super super nice if the charts would natively support showing different YAxis on the same XAxis (which is especially useful for charting time scale data)
Sounds like a great proposal, I'll see what I can do. Thanks for helping out in making this library become better and better :)
Thank you so much!
I'm really sorry I haven't made any PRs yet — when time allows, this is the first library I'll contribute to :) Thank you for all your great work on this!
What is the problem?
Props received by children of StackedAreaChart are different than those received by the AreaChart (which all in all is ok), but they dont seem to contain enough data to create decorators from (e.g can't calculate X / Y because the data array may contain objects)
When does it happen?
When you try to follow any of the examples to render decorators as children, but using StackedAreaChart
What platform?
React Native version: 0.55.2
I'm liking the new 5.0, but StackedAreaChart seems to be a special child that needs a little bit more love :(