-
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
Draw inner border for arc elements #5841
Conversation
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.
It looks really good @nagix, though it breaks one (common?) use case: same border color for all slices with same width on all edges. With your changes, external edges will be half the size of the internal ones and I think it can cause trouble to some of our users, what do you think?
Also, I noticed a few glitches on your fiddle when changing the border color:
The miter limit seems problematic with tiny slices:
Drawing half border doesn't fix the issue in case of multiple datasets: Putting aside glitches (manually removed on the screenshot), I agree that the result looks better when border colors / widths are different but in this specific case, which may be common, I don't find the result very aesthetic (but that's subjective). I don't know what the best way to handle that case, neither if we need to handle it (I think we should). An idea would be to preserve the old behavior (with your new calculations) and implement alignment behind a new option? Something like |
It's quite rare to see super tiny slices in pie / doughnut charts. Usually these are all grouped together under a category like "Other". There's probably some size under which we would need to decide that we're not going to render an individual slice The pie chart with the smallest slices I've ever seen is the one below. Even on it you get to a point where the individual slices are no longer being rendered and you're just seeing the white border |
@benmccann tiny slices happen on animation |
33c9822
to
946ffa0
Compare
I added a new To eliminate glitches between borders, the clipping area is enlarged by 0.33 pixels. In addition, |
Updated the jsfiddle and images above |
56e5c62
to
125626f
Compare
max = hoverWidth > max ? hoverWidth : max; | ||
for (i = 0, ilen = arcs.length; i < ilen; ++i) { | ||
custom = arcs[i].custom || {}; | ||
borderAlign = custom.borderAlign ? custom.borderAlign : valueAtIndexOrDefault(dataset.borderAlign, i, elementOpts.borderAlign); |
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.
I think we should avoid to resolve element options twice (also done in updateElement
). We could store resolved options in element._options
(as done in the bubble controller) before computing max border width and updating element, something like:
update: function(reset) {
// ...
for (i = 0, ilen = arcs.length; i < ilen; ++i) {
arcs[i]._options = me._resolveElementOptions(arcs[i], i);
}
// compute chart.borderWidth, innerRadius, ...
for (i = 0, ilen = arcs.length; i < ilen; ++i) {
me.updateElement(arc, index, reset);
}
}
updateElement: function(arc, index, reset) {
var options = arc._options;
// ...
}
Note: I would not implement scriptable options in this PR.
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.
_resolveElementOptions
has been added. As the visible outmost dataset can be different from the current one, the cached values is used only when they are the for the current dataset in getMaxBorderWidth
.
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.
I didn't realize that getMaxBorderWidth()
, when called without parameters, was computing the width based on the outmost visible dataset, which is most of the time not the same as the current one when there is more than 1 dataset.
It's not really optimal because _resolveElementOptions
get called 2 * datasets.length - 1
times per chart.update()
while ideally getMaxBorderWidth()
should be called only one time, so _resolveElementOptions
only datasets.length
times. This can be a performance issue when we will introduce scriptable options but not sure how to make that better right now since there is no way to centralize these computations for all datasets.
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.
Looks good! I like the idea of the option for the alignment. I agree with @simonbrunel's comment regarding caching the options
I didn't touch In the |
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 little bit worry about this comment but it should be fine in most cases. I think we can merge this implementation and later investigate solutions that prevent to compute getMaxBorderWidth
for every dataset.
Thanks @nagix
Currently, the border of arc elements is aligned to the center, but this causes a few problems:
With this PR, the border is drawn inside arc elements in the same way as rectangle elements. This fixes the issues above and the following issues as well.
lineJoin
is set to'bevel'
.'miter'
should be betterborderWith
was not correctly reflected in theouterRadius
Chart.js 2.7.3: https://jsfiddle.net/nagix/tj1na4vm/
This PR: https://jsfiddle.net/nagix/87wvucjy/
Fixes #2381
Fixes #5645