-
Notifications
You must be signed in to change notification settings - Fork 11.9k
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
Weird curve path if "max" limit is set for line chart #11273
Comments
Hello, @etimberg, I believe I may have pinpointed the underlying cause of this issue, but please correct me if I'm mistaken. It seems that the problem originates from line 51 of the LineController class. There, we have a conditional check to determine whether the scale ranges have changed. If they have (which seems to be true for the first render), we replace the count variable with the length of the points array. However, in this particular situation, the points array has a length of 8, while a user-defined max value truncates the array at the 5th element. Consequently, setting the count variable to an incorrect value results in the generation of erroneous points within the updateElements function called at line 73. Since I'm still familiarizing myself with the codebase, I'd like to avoid making hasty decisions. However, my suggestion would be to pass |
Looping in @stockiNail and @LeeLenaleee in case they know how to handle this. Thanks. |
@mukham12 I am currently in vacation without my laptop. I could have a look at the beginning of July if still open. |
@mukham12 your theory sounds correct. I don't recall why we set it to the number of points in that case. You could try setting it to the truncated length and seeing what happens. One reason I could see why this code exists is so that points that are animating off the canvas aren't removed suddenly. |
Setting the value to the truncated length is producing the correct chart (without the “weird” curve). That is what led me to this theory in the first place. |
@mukham12 could you send a PR with those changes? I'd like to test them and see how they work |
After some reflection, it seems I jumped to a hasty conclusion. The modification I suggested worked fine at first, but it broke when the screen was resized. I will investigate further before making any pull requests. On the bright side, we now know about this issue and are making progress in identifying the bug. I will keep you updated. @stockiNail your assistance would be appreciated once you return from vacation. |
Perhaps the solution is to only do do the if when it's not the first render. Something like if (!firstRender && _scaleRangesChanged(meta)) {
...
} Off the top of my head though I'm not sure if we have a way to detect the first render |
I also considered that option, but I'd prefer to keep it as a last resort. There must be a reason why the initial rendering isn't displaying correctly and only adjusts to the correct appearance after resizing the screen or interacting with the legend. |
I have revisited the code and made another observation worth considering. The As a result, all 8 points will be considered for drawing, since none of them will have for (let i = 0; i < pointsCount; ++i) {
const point = points[i];
const properties = directUpdate ? point : {};
if (i < start || i >= end) {
properties.skip = true;
point.skip = true; // Will ensure the points are not considered for drawing
continue;
}
.
.
.
} Apologies for continuously bringing up new observations, but this approach could address the issue. Please let me know your thoughts and I can create a PR. You can review the relevant code snippet underneath. Thanks Chart.js/src/controllers/controller.line.js Lines 75 to 96 in 57bbd82
|
The properties are applied to the points through animations, unless directUpdate is true (meaning props are applied directly without animation) I think the proposed change should do nothing with direct update and with animation it should make points to be skipped too early. |
I completely agree with your observations. If the animations are disabled this issue does not occur since However, with animations enabled, we encounter a different scenario. The points are not directly modified by the code. Consequently, the Or the issue could be something entirely different. |
I had a look to the code. I think, but maybe I'm wrong, that the line controller is setting all the points (ignoring the scale limits) to the line element. Locally, I have changed
to line.points = points.slice(this._drawStart, this._drawStart + this._drawCount); where the points of line element are only the "drawable" ones. Sounds working and also the regression tests. |
Rethinking a bit that is not the final solution because the line will be drawn only between the visible points and maybe is not correct. need more time |
Hi @stockiNail. Thanks for looking into this. No, you are absolutely correct. LineController is setting all the points. I’ve been trying to convey that in my earlier comments and perhaps did not do such a good job. There are perhaps a few solutions to this, but I was thinking explicitly setting the ‘skip’ property inside the function which creates Point elements would get the job done. Excited to see what you’ll come up with :) |
@mukham12 the solution that I have prepared above is working correctly if the scale limits (min and/or max) have the same value of a point. If not, the line will "join" only the point drawable and that's not correct :(. Therefore I think we could have 2 options (but feel free to correct me):
I'm going to go on tomorrow or later. |
@stockiNail, I trust in your expertise to make the best decision here. Whichever option you believe will accomplish the task more efficiently, please go ahead with it. Considering your familiarity with the codebase, you can resolve this more swiftly than myself. Many thanks for your assistance. |
@stockiNail Looks great. Thanks 😊 |
Expected behavior
If the
max
limit is set for the x axis of a line chart, and the tension is set, orcubicInterpolationMode
is set tomonotone
, then there's a weird curve path at the end of the graph.If you have two lines on the chart, and you deselect one of them and then reselect it, the lines are being redrawn, and the curve path straightens out to what it should like from the beginning.
This is how it then looks and how I expected it to look without interaction:
Current behavior
And this is how it looks like initially:
Reproducible sample
https://codepen.io/rgwebcode/pen/mdzpzrQ
Optional extra steps/info to reproduce
Happens both in standalone Chart.js and react-chartjs-2.
Possible solution
No response
Context
No response
chart.js version
v4.3.0
Browser name and version
Chrome 112.0.5615.138 & Firefox
Link to your project
No response
The text was updated successfully, but these errors were encountered: