-
Notifications
You must be signed in to change notification settings - Fork 19.7k
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
fix(polar): angleAxis extent when boundaryGap is false #20184
base: master
Are you sure you want to change the base?
Conversation
Thanks for your contribution! The pull request is marked to be |
@@ -102,9 +102,15 @@ function updatePolarScale(this: Polar, ecModel: GlobalModel, api: ExtensionAPI) | |||
// Fix extent of category angle axis | |||
if (angleAxis.type === 'category' && !angleAxis.onBand) { | |||
const extent = angleAxis.getExtent(); | |||
const diff = 360 / (angleAxis.scale as OrdinalScale).count(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can see that the old code takes 360
as the range of endAngle
to startAngle
, which is not always the case.
The changes brought by this PR can be previewed at: https://echarts.apache.org/examples/editor?version=PR-20184@c36098a |
angleAxis.setExtent(extent[0], extent[1]); | ||
const angleModel = angleAxis.model; | ||
const endAngle = angleModel.get('endAngle'); | ||
const spanAngle = (endAngle == null ? 360 : endAngle - angleModel.get('startAngle')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The conditional operator has lower precedence than arithmetic operator.
endAngle == null ? 360 : endAngle - angleModel.get('startAngle')
means
endAngle == null ? 360 : (endAngle - angleModel.get('startAngle'))
This should be a "famous" and commonly occurring mistake in not only JS but also Java, c++, ...
And why there is null checker for only endAngle
but not startAngle
?
I think in this place we can assume that both endAngle
and startAngle
are not nullable here. I mean that set default value in only one place (function setAxis
).
And should we retrieve value from extent
rather from angleModel here?
clockwise: true, | ||
testNext: () => { | ||
config.startAngle = 90; | ||
config.endAngle = -90; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a tiny problem. when clicking on 'testNext', the 'endAngle' in dat.GUI isn't updated, which caused confusion a little bit.
(It's OK not to fix it.)
const diff = spanAngle / (angleAxis.scale as OrdinalScale).count(); | ||
if (Math.abs(spanAngle + diff) >= 360) { | ||
extent[1] += Math.abs(diff); | ||
angleAxis.setExtent(extent[0], extent[1]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the current modified approach, this cases are not reasonable enougth:
(already have a overlap between bar C and bar D) (endAngle changes a little (from -195 to -198) but the appearance changes significantly.)I think the "adjusting the extent" is a compromise. It's counter intuitive (the adjusted endAngle is not what use specified) but with out that user have avoid overlap manually.
I just try to modify it: make it keep at a "max span" when there is no enough space.
// Fix extent of category angle axis
if (angleAxis.type === 'category' && !angleAxis.onBand) {
const extent = angleAxis.getExtent();
let spanAngle = normalizeAngle((normalizeAngle(extent[1]) + 360 - normalizeAngle(extent[0])));
if (angleAxis.inverse) {
spanAngle = 360 - spanAngle;
}
const spanLimit = 360 - 360 / (angleAxis.scale as OrdinalScale).count();
if (spanAngle >= spanLimit) {
extent[1] = extent[0] + (angleAxis.inverse ? -1 : 1) * spanLimit;
angleAxis.setExtent(extent[0], extent[1]);
}
}
// FIXME: this kind of function should be placed in some common util file? (or similar one already exists?)
// Normalize an angle value to `[0, 360)`.
function normalizeAngle(val: number) {
val = val % 360;
val < 0 && (val += 360);
return val;
}
(it's just a illustrative code to show my current understanding.)
But about clockwise (inverse). I haven't understood the logic yet.
The current behavior (before this PR modified) seems weird:
Brief Information
This pull request is in the type of:
What does this PR do?
When angleAxis in the polar system has
boundaryGap: false
, the extent is adjusted since this commit so that polar bars don't overlap each other. The main idea is to make extra space according to data count. But it may overkill in some situations.Fixed issues
NA.
This PR is not a fix to #20172 , which is not a bug.
Details
Before: What was the problem?
Consider the case when
startAngle: 90, endAngle: -90
, before this PR, it has the result of:This is not as expected because a developer set
startAngle: 90, endAngle: -90
would expect the range to be half a circle.After: How does it behave after the fixing?
The extent of angleAxis with
boundaryGap: false
should only be adjusted if it has the potential to overlap, that is to say,startAngle: 90, endAngle: -90
should still get half a circle:while
startAngle: 90, endAngle: -270
should get 3/4 of a circle:Please also not that if the range of startAngle and endAngle itself is over 360 degrees, it won't adjust to be smaller than a circle because it is not expected to.
Document Info
One of the following should be checked.
Misc
ZRender Changes
Related test cases or examples to use the new APIs
I added a test case under
test/bar-polar-basic-radial.html
.I've run with
npm run test:visual
and it passes all but the above case.Others
Merging options
Other information