chartjs / chartjs-plugin-annotation

Annotation plugin for Chart.js
MIT License
603 stars 325 forks source link

Enable centered label drawing for doughnut controllers #825

Open stockiNail opened 1 year ago

stockiNail commented 1 year ago

A prototype. This PR is enabling the possibility to add an inner label in the middle of a doughnut controller. This is leveraging on the already label calculation and drawing used for label annotation.

image text
inner2 inner1
inner4 inner3

SAMPLE chart configuration:

{
  type: 'doughnut',
  data: {
    labels: ['Data1', 'Data2', 'Data3', 'Data4'],
    datasets: [ {
      data: [102, 200, 80, 55],
    }],
  },
  options: {
    aspectRatio: 2,
    plugins: {
      annotation: {
        annotations: {
          innerlabel: {
            type: 'doughnutLabel',
            display: true,
            drawTime: 'afterDraw',
            font: [{size: 24},{size: 16, weight: 'bold'}],
            click(context) {
              console.log("click", context);
            },
            color: ['blue', 'red'],
            content: ({chart}) => ['Utilization', chart.data.datasets[0].data.length + '%'],
          }
        }
      }
    }
  }
}

TODO

stockiNail commented 1 year ago

I don”t think the innerlabel is needed. All can be mamaged by annotation plugin. New updates asap

kurkle commented 1 year ago

About the animations, without reading any code;

The element and its options were designed to be the "view", containing currently displayed value for everything.

I'm guessing you are using an array of colors for the lines of text?

In this "philosophy", each line should be an "element", containing its resolved current display values.

I put quotation marks around the element, because from the animations point of view, it can be any object.

Now, I'm out of context wit the annotations plugin, but I think something like sub elements is a thing or was it abandoned?

stockiNail commented 1 year ago

I'm guessing you are using an array of colors for the lines of text?

yes, that's correct

In this "philosophy", each line should be an "element", containing its resolved current display values.

I understand the philosophy and I agree. But a value is a value, also an array could be a value ;), therefore the implementation it should not be against of that philosophy, I guess. About the plugin implementation, to have an element for each row of a label when a content is a text, sounds to me adding complexity to manage events, options (like padding, borders, etc) which I don't think make sense to address because a complete refactoring should be needed with a few vantages. Furthermore I'm expecting that also the performance will be affected, having potentially many elements to manage for each row.

I put quotation marks around the element, because from the animations point of view, it can be any object.

I have to admit that this use case forced me to go more in deep how animation is working and I have learned more, that's good! Nevertheless, staying on this use case and the plugin itself, the animation was thought (at least for what I had understood) only for the properties of the elements and not for their options. In fact we have only 1 animations configuration, based on the properties of the elements. And, in my opinion, doesn't make sense to extend it to the options (like color, bordeColor, etc.). And this animations setup (for colors) is coming from the controller which is implementing that, and plugin animations config is falling back to that. Maybe you disagree, but I think that assign the option to the element after animation item creation sounds good even if not 100% align with the designed element model and its philosophy. What do you think? I would suggest to stay with this implementation, simple, fitting the requirement and working without big effort.

I think something like sub elements is a thing or was it abandoned?

It's still present for all labels and the points (for polygons). Nothing is changed. But, as written above, it doesn't seem to make sense to have sub-elements for each row. I think good compromise is what I described above, assign options to element after animation item creation.

Now, I'm out of context wit the annotations plugin,

Ok... may I ask what it means exactly? is it just a period and it will be forever? I'm worried that you will leave the project... :worried:

kurkle commented 1 year ago

I understand the philosophy and I agree. But a value is a value, also an array could be a value ;), therefore the implementation it should not be against of that philosophy, I guess. About the plugin implementation, to have an element for each row of a label when a content is a text, sounds to me adding complexity to manage events, options (like padding, borders, etc) which I don't think make sense to address because a complete refactoring should be needed with a few vantages. Furthermore I'm expecting that also the performance will be affected, having potentially many elements to manage for each row.

Yes, it might not be appropriate. Though then you could have hover / click effects for each row etc :) Anyway, array is also a value, it just can't be animated. It should be possible to provide animation defaults for the element to disable animation of the options that should not be animated. (still did not look at the code, sorry :))

Another option could be to use something else, like textColor for that, which would not be animated by default.

Now, I'm out of context wit the annotations plugin,

Ok... may I ask what it means exactly? is it just a period and it will be forever? I'm worried that you will leave the project... 😟

It jus means its been long enough that I don't remember how things are anymore (hence the question about sub elements). I still did not have the time to invest in these projects, sorry about that. Does not look good for today either :/.

stockiNail commented 1 year ago

It should be possible to provide animation defaults for the element to disable animation of the options that should not be animated.

I put it in my TODO. I will have a look in next days. I think it could make sense, only for color option.

Another option could be to use something else, like textColor for that, which would not be animated by default.

Personally, I don't like it because it's a deviation of the other plugins and chart.js itself where they are using color for text color. And a breaking change as well.

It jus means its been long enough that I don't remember how things are anymore (hence the question about sub elements). I still did not have the time to invest in these projects, sorry about that. Does not look good for today either :/.

Fiuuuu... 😄 ... I had some time during the Christmas period but starting from next Monday, I will not have much time as well.

stockiNail commented 1 year ago

Anyway, I'm still working on this PR and I'd like to have something really consistent to show you asap (apart the discussion about animation). I have refactored it during last 2 days to provide the background inside the doughnut controller (and not the box around the label which doesn't make sense).

stockiNail commented 1 year ago

@kurkle, about color option animation, I have disabled it for the plugin, only for color, not for the other colors like background or border.

    animations: {
      numbers: {
        properties: ['x', 'y', 'x2', 'y2', 'width', 'height', 'centerX', 'centerY', 'pointX', 'pointY', 'radius'],
        type: 'number'
      },
      colors: {
        properties: ['color'],
        type: 'color',
        duration: 0
      }
    },

What do you think?

kurkle commented 1 year ago

@kurkle, about color option animation, I have disabled it for the plugin, only for color, not for the other colors like background or border.

    animations: {
      numbers: {
        properties: ['x', 'y', 'x2', 'y2', 'width', 'height', 'centerX', 'centerY', 'pointX', 'pointY', 'radius'],
        type: 'number'
      },
      colors: {
        properties: ['color'],
        type: 'color',
        duration: 0
      }
    },

What do you think?

Does not have to be a group, unless you want to disable the whole group:

    animations: {
      numbers: {
        properties: ['x', 'y', 'x2', 'y2', 'width', 'height', 'centerX', 'centerY', 'pointX', 'pointY', 'radius'],
        type: 'number'
      },
      color: { duration: 0 }
    },

I'm not sure if element default apply here, but it could also be disabled just for some elements, so you can have animated color changes for hover effects in others.

stockiNail commented 1 year ago

Does not have to be a group, unless you want to disable the whole group:

At the beginning , I have done as you suggested but in this way I disabled ALL color properties. I thought that setting only the color, only the color will be disable but the rest will remain. Let me do a test because I was quite sure

stockiNail commented 1 year ago

Could the following config reasonable for you?

      colors: {
        properties: ['backgroundColor', 'borderColor'],
        type: 'color'
      }

Where we can animated background and border colors. We have other colors (for shadowing and textStroke) but maybe there couldn't be included.

stockiNail commented 1 year ago

I'm not sure if element default apply here, but it could also be disabled just for some elements, so you can have animated color changes for hover effects in others.

Maybe I'm wrong but hover colors must be managed by the plugin because it's not managed by Chart.js, for plugins.

stockiNail commented 1 year ago

@kurkle the PR has been rebased and has got new features/changes applied in other merged PRs (like init and opacity options for labels).

stockiNail commented 1 year ago

@kurkle apologize because your approval was dismissed. PR had to be rebased

mesqueeb commented 5 months ago

@kurkle what would be the steps needed to get this merged? 🤩

stockiNail commented 1 week ago

@LeeLenaleee I have rebased. Ready for review, when you have time.