chartjs/chartjs-plugin-annotation

Annotations that are following current Y values should not overlap

davidnir1 opened this issue · 10 comments

Feature Proposal

When two plots have very close Y values, the annotations are overlapping and can hide each other, for example in our app:
image

Possible Implementation

Instead of overlapping, they should be on top of each other (ordered by y values), for example (source):
image

Thanks!

@davidnir1 may I ask you if you are using annotations or the annotations you are referring to are the tooltip labels? If you are using annotation plugin, can you share a sample?

@davidnir1 anyway, if you are using the annotation plugin, the labels can be overlapped.
See discussion #880
You can use y/xAdjust options to manually change the label position. They can be scriptable.

@davidnir1 anyway, if you are using the annotation plugin, the labels can be overlapped. See discussion #880 You can use y/xAdjust options to manually change the label position. They can be scriptable.

Hi, in this example you reffered to i`m not sure what is x,x2, y,y2 ,Here is an example on how we add annotation (using annotations plugin):
image

which means I can only control yValue for the location of the annotation, however I find it difficult to identify collisions because I have cases of multiple y scales whos values are totally different and yet there may be collision between the annotations because the chart is normalized.

@KseniaKeren you are right writing that it is not simple.
Anyway, to do that, you could implement beforeDraw hook (https://www.chartjs.org/chartjs-plugin-annotation/latest/guide/configuration.html#hooks) at annotation level where you can have the element to draw with its dimension (https://www.chartjs.org/chartjs-plugin-annotation/latest/guide/types/label.html#element).
Furthermore, due to the fact you need to compare the dimension with other annotations, the PR #892 sounds to be needed.

i`m not sure what is x,x2, y,y2

@KseniaKeren sorry, I forgot to explain better the above doubt.
Every annotation is an Chart.js element which is taking care to draw what is requested by the config.
Every annotation element has got a set of properties and there are some of them related to the dimension of the element (and then of the annotation.
All annotation elements are mapped in a rectangle, which contains x and y (left-top edge) and x2 and y2 (right bottom edge).
Furthermore the element has got the width and height properties.
The element are available on scriptable options (https://www.chartjs.org/chartjs-plugin-annotation/latest/guide/options.html#option-context) and hooks (draw and event).

See elements diagrams:

Annotation type Diagram
box image
ellipse image
label image
line image
point image
polygon image

@stockiNail Thank you very much for the explanation ,your thorough explanations and thoughtful suggestions have greatly improved my understanding.
is there a way to add the beforeDraw hook to the annotation level? because when I try to add it I get a ts error

image

also I wanted to see the elements x2 y2 values but when I print the annotation element to the console these are the fields I have

image

@KseniaKeren I think you are still using the annotation plugin version1.x.
The element properties normalization (with those properties) is available since version 2.x.
The beforeDraw hook is available from version 2.2.0.

@davidnir1 @KseniaKeren here is a codepen with a sample how to avoid label overlapping: https://codepen.io/stockinail/pen/xxQKPKv
It could be a starting point for custom logic.

@stockiNail Thank you very much, I looked into the code and it seems to be very helpful for us. Also I updated our version and now we indeed have the beforeDraw hook. a challenge we encountered now is about how to access other annotations in the chart. I wonder if there is a way to access them in the chart context that comes as a parameter to the beforeDraw hook? we cannot use the custom plugin you written cause our annotations are always shown the only thing we change in the app is the x value (kind of progress bar of a clip that constantly moving) , so we cannot seem to find a way to access all other annotations. We used to access them via chart.options.plugins.annotation.annotations[i] in order to change the yValue each time the current x changed, but this is the inner propeties of the annotation and they do not include the x x2 y y2 properties.

@KseniaKeren to get all annotation elements there is a "private" method which can be removed if and when #892 will be approved and merged.
After that PR, you could get a method in the plugin to get all visible annotations.

// get annotation plugin instance
import annotationPlugin from 'chartjs-plugin-annotation';
....
const myLineChart = new Chart(ctx, config);
// get all annotation elements
const elements = annotationPlugin.getAnnotations(myLineChart);

If you cannot wait for that PR, you can have a look to the discussion (previously mentioned) #880 (reply in thread) where the sample is using the private and undocumented function.
But pay attention, because this will be removed by above mentioned PR.