-
-
Couldn't load subscription status.
- Fork 1.7k
[charts] Place ordinal ticks according to a continuous scale #19808
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
Deploy preview: https://deploy-preview-19808--material-ui-x.netlify.app/ Updated pages: Bundle size report
|
CodSpeed Performance ReportMerging #19808 will not alter performanceComparing Summary
Footnotes |
Evenly spaced dates are a bit hard because of how many days there are in months, in some instances you will never be able to plot nice even labels because you are between january and april, and february has 28 for some reason so it will mess everything up 🤷 |
|
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
I propose we open an issue in the international metric institute to ask them a breaking change on the way day and months are organized 😇 |
What I was suggesting is that we follow what d3 is doing. We provide a suggested tick number and we try to place them. Let's say there's 19 ticks (prime number, so not easily divisible). If we want 2 ticks we place them such that the number of bars to the left and right of each tick are the same. If there's 19 ticks, we have 17 bars to distribute: for even spacing let's place the first tick in the 6th bar (5 bars distance to the start), then the last tick on the 14th bar (7 bars distance to the first tick, and 5 bars distance to the end). Alternatively, we can make it so there's 6 bars before the first and 6 bars after the last, with a spacing of 5 bars in the middle. Let's say we want to lay out 3 ticks. This means we have 16 bars left, which means there's a 4 bar spacing between each tick. For four ticks: 15 bars left: 3 spaces each. If there's a number that doesn't work, we could try a greater number, then a smaller one. I can try to write an algorithm for this, but I think we might be able to make it work. If we change the tick number, there must always be an evenly spaced solution.
It seems the ticks are changing position slightly, but it does seem there's a fixed number of ticks for that size and they are adjusted slightly. |
If we want to say that the band is continuous, we might as well use For next version I don't mind having it automated, but it needs to make sense
Can't we use d3 for the small dates as well? If we provide the visible data to d3 and ask for formatting, wouldn't it provide the values for us?
We could accept both,
Tick placement is annoying, I had to handle it in the grouped axis as well. You could try to put it in the middle of the band when the continuous value is inside the band. They would be in the correct place, but not evenly spaced though.
There could be an option to forcibly put the first and/or last ticks in, however value the min/max of the current view is 🤔 |
Yes, I suspect the small modification are due to the tick falling exactly on the value point. So if the zoom level shows 100 of 102 point the pixel value change a bit
Yes, it will display The reason being D3 ticks for dates picks a step (year, months, days, hours, ...) according the the data domain. And set all the smaller units to 0. So if the step is months, D3 will generate dates with In out case we have
Easier to say than to do. Is |
Can't we define if a tick is inside a band or not based on the tick X value? bandTicks = [
{x: 0},
{x: 10},
{x: 30},
{x: 50},
]
continuousTick = {x: 12}
band = bandTick.find((v,i,a) => v.x <= 12 && a[i+1].x >= 12 ) |
All you know is that tick 12 is between band 10 and band 30. The question is the tick inside the band or between the two is still open. But we can also just say all the ticks are either always between two band or always in the middle of bands It's easier to consider numbers, because you can always say the 12 should appear between 10 and 30. |
I meant to use the X value of the tick position, it has almost nothing to do with the band 😆 |
|
I looked deeper on most of the financial charts I could think about.
A strategy where tick detect if there is a month change from one value to another looks more promising |



Fix #19531
Open topics
Using an attribute
Adding a
isNumericalattribute to enable the feature. This attribute is a way for the user to say "my data are number/date" and the are kind of evenly spaced.For this major the need seems obvious. For next version, it's up to debate.
IMO it's necessary. I'm a conservative person, an ordinal scale should behave as an ordinal scale except if the devs set options saying the opposite.
But I get it's convenient to say "if I provide numbers or date, it's assuming they are evenly spaced. To get categories I need to provide string"
Formatting
After playing a bit with it, I think the formatting function should get the tick value as a first argument. That's because those value are designed to be human readable so the one you want to format.
A remaining issue is the switch between tick values and band values while zooming.
In the demos for now it's hidden by
value.toLocaleDateString()which always format ticks in a consistent way.But if you use the default time formater, the initial ticks are better. Up to the moment you reach the "one tick per band".
The reason is nice ticks set hours to 00:00. So the default d3 formater knows there is no time specify and so ignore it.
The data contains either 01:00 or 02:00 so the default formatter displays the hours which is not the expected behavior.
I need a way to let the user know when we swich from one tick management to the other. But sure yet about how to do that
Smart switch between linear/band ticks
Currently I propose to do the switch when the number of ticks in linear versus band is 1/3:
Roughly the idea is the following: If we reduce a lot the number of ticks we apply it. If it's nearly the same we use the more accurate.
But I'm open to other criteria. Maybe a band size. Such that if band is more than 20px we display a tick per band. If less than 20px we use linear scale to sub-sample to ticks.
Tick placement
I tried to rely on the theoretical position of ticks (according to the continuous scale to know if I should place them at the beginning/middle/end of the band. But it's not supper nice. For example here it would be better that the tick appears in the middle of the band since it's "exactly" the same value.
The root cause was different. The formatted value was the wrong one (the band instead of the tick) so it was of course miss leading.
first/last ticks
The case of the first/last tick is tricky. Because if your data are starting at 1 it would be nice on, a large scale to put a tick 0 before the first band. But 0 is outside of the range.
For now I do it that way:
nice()version of this linear scale