artus9033 / chartjs-plugin-dragdata

Draggable data points plugin for Chart.js
MIT License
266 stars 56 forks source link

Implement a way to use a custom point search to attach the listener #116

Closed Ruanrls closed 1 month ago

Ruanrls commented 1 year ago

Problem

Sometimes the users need to use custom interaction mode, which is provided by react charts. E.G: If exists 2 datasets and only one of them is draggable, you can only move the dataset which has enabled dragData if the cursor is nearest (by default) to the dataset that you want otherwise no points will be dragged.

Using the nearest position is not always the correct behavior. As the developer could implement your own interaction mode.

You can check this problem here:

https://user-images.githubusercontent.com/49437895/220757355-c51edf56-d4c3-40ea-92f7-33aa11794110.mov

Solution

Implement a custom way to define which interaction mode the developer will use.

PR

115

References

Custom interaction modes

chrispahm commented 1 year ago

Hey @Ruanrls

Thanks for your contribution and working on a PR! This is indeed a very tricky issue, and I haven't seen a good UI/UX solution so far. Without using any plugins, it is possible to hide datasets in Chart.js by just clicking the datasets label in any Chart.js chart:

https://user-images.githubusercontent.com/20703207/220921027-340ed13e-dc40-47e3-bf6f-ca2ddad1b78e.mp4

While I absolutely agree that the feature is not intuitive (nor easy to find), it is very simple to use. Users can just hide all datasets that they don't want to change, and get a predictable result.

Can you elaborate further how your custom approach would look like?

Ruanrls commented 1 year ago

@chrispahm It should be flexible to a custom implementation, varying from dev to dev.

In my PR #115 for example, we can change the default interaction mode which is 'nearest' to a custom implemented by the dev. It can be any custom implementation, following this section from chartJs documentation and then using the dragData?.interaction.mode object we can change this default behavior to be another custom implementation.

Sample code

Add a custom interaction mode to your chartJs

Interaction.modes.myCustomMode = function(chart, e, options, useFinalPosition) {
  const position = getRelativePosition(e, chart);

  const items = [];
  Interaction.evaluateInteractionItems(chart, 'x', position, (element, datasetIndex, index) => {
    if (element.inXRange(position.x, useFinalPosition) && isTheHighestDatasetOrder(element)) {
      items.push({element, datasetIndex, index});
    }
  });
  return items;
};

And then add to dragData plugin the new interaction mode to use to select which point to drag:

const options = {
    ...yourOptions,
    plugins: {
        dragData: {
            interaction: {
                mode: 'myCustomMode'
            }
        }
    }
}

This way this issue should be fixed permitting this custom implementation: at src/index.js:

Ruanrls commented 1 year ago

@chrispahm Any updates?

artus9033 commented 1 month ago

Hi @Ruanrls! I am the new maintainer and would like to bring this issue & PR back to life. Nice catch, indeed this is a feature that should be supported.

I posted a message in the discussion over #115 - let's continue it there.

artus9033 commented 1 month ago

Closed by #115