Skip to content
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

Ability to sync the dtick values of multiple y-axes with new tickmode value "sync" #6356

Open
wants to merge 50 commits into
base: master
Choose a base branch
from

Conversation

VictorBezak
Copy link
Contributor

@VictorBezak VictorBezak commented Nov 2, 2022

The Issue

#1962

Developers:

Our Solution

This PR is an attempt to adapt the logic originating from https://github.com/VictorBezak/Plotly_Multi-Axes_Gridlines
in order to integrate it with the plotly schema. This PR is not fully tested and ready to be merged, but we wanted to get some feedback at this stage as we feel we now have a viable MVP solution.

How To Use

  • You can now set tickmode: "sync" on your 2nd yaxis that also has property overlaying set.
  • for testing, we've added a new mock called new_tickmode_sync.json

Things Tested and Working

  • positive/negative ranges
  • zoom
  • click & drag y-axis up/down

Not Done Yet

  • we haven't written any tests yet!

@VictorBezak VictorBezak changed the title First poc tickmode sync Ability to sync the dtick values of multiple y-axes with new tickmode value "sync" Nov 2, 2022
@VictorBezak
Copy link
Contributor Author

VictorBezak commented Nov 2, 2022

@alexcjohnson @jackparmer @archmoj
I've been receiving help for the last 5 weeks from fellow developer, Filipe Santiago @filipesantiagoAM, and together we've managed to put together an MVP solution!

@fsantiago99
Copy link

fsantiago99 commented Nov 11, 2022

@archmoj @alexcjohnson Could you have a look here and give us some feedback please?

@archmoj
Copy link
Contributor

archmoj commented Nov 11, 2022

Thanks very much for the PR.
The image test is broken now.
Please rename new_tickmode_sync.json to z-new_tickmode_sync.json.
Then download the baseline here and place it at test/image/baselines/z-new_tickmode_sync.png.
Thank you!

src/plots/cartesian/axes.js Outdated Show resolved Hide resolved
src/plots/cartesian/axes.js Outdated Show resolved Hide resolved
@archmoj
Copy link
Contributor

archmoj commented Nov 11, 2022

This is pretty cool. When I drag the right axis the grid lines stay at their initial locations and only the tick labels are updated.
Wondering if you could possibly make that for the other axis i.e. when dragging the left axis the grid lines stay there?

@filipesantiagoAM
Copy link
Contributor

filipesantiagoAM commented Nov 14, 2022

All good with the checks here.

Wondering if you could possibly make that for the other axis i.e. when dragging the left axis the grid lines stay there?

@archmoj I was trying to put this to work but looks a bit tricky because when we drag one axis, this should be the only one who refreshes the ticks. If I automatically refresh the others should be a bit mess, especially when we have more than two axes and some are connected and some not, if it makes sense. Of course I'm open to hear your tips and tricks to approach this feature. Thanks

@filipesantiagoAM
Copy link
Contributor

filipesantiagoAM commented Nov 16, 2022

@archmoj I know this PR requires more effort to be merged but if you could have a look and give us some feedback would be great. This is the most desired feature for me in plotly.js.

Thanks

@@ -1463,7 +1463,8 @@
"values": [
"auto",
"linear",
"array"
"array",
"sync"
Copy link
Contributor

@archmoj archmoj Nov 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

colorbar.tickmode should not have sync option.
You can override tickmode for colorbar here:

tickmode: axesAttrs.tickmode,

Something like:

    tickmode: extendFlat({}, axesAttrs.tickmode, {
      dflt: values: ['auto', 'linear', 'array'],
      description: { /* only include available options */ }
    }),

Copy link
Contributor

@archmoj archmoj Nov 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly for indicator trace we don't need this option.
Please modify here:

tickmode: axesAttrs.tickmode,

test/plot-schema.json Outdated Show resolved Hide resolved
@archmoj
Copy link
Contributor

archmoj commented Dec 23, 2022

Looking great.
Now in order to fix the case of moving the base axis (which make other axes out of sync), you may change args of axes.draw function something like:

axes.draw = function(gd, arg, opts) {
  if(args && args.length === 1) {
    // add the ids of other axes if they are synced to this axis
    args = args.concat(aboveList);
  }
  
  ...
};

@archmoj That's a really nice tip! I wouldn't do it without you! Done now :)

Getting closer. But I still think we should move the logic to the start of axes.draw. Right now the other axes do not update until mouse which could be fixed by that adjustment.

@archmoj Sorry but I tried to move it up in the callstack and no luck. I'm not sure what I can do in order to have what you want.

I see. Let's tweak this function

function ticksAndAnnotations() {

That should fix updating sync axes while dragging the base axis.

@archmoj
Copy link
Contributor

archmoj commented Dec 24, 2022

The behavior now looks great! 🏆
Which axis types should we allow sync option e.g. linear and category?
It appears the log axes may work too.
Could you please test that?

@filipesantiagoAM
Copy link
Contributor

filipesantiagoAM commented Dec 26, 2022

The behavior now looks great! 🏆 Which axis types should we allow sync option e.g. linear and category? It appears the log axes may work too. Could you please test that?

@archmoj All looks ok to me: linear, log, date, category and multicategory.

var vali = ax.p2l(pos);
var val1 = ax.p2l(pos - 0.5);
var val2 = ax.p2l(pos + 0.5);
var d = 1 + Math.round(Math.log10(Math.abs(val2 - val1)));
var e = Math.pow(10, -d);
var valR = Math.round(vali * e) / e;
var objR = axes.tickText(ax, valR);
var obj = axes.tickText(ax, vali);
Copy link
Contributor Author

@VictorBezak VictorBezak Dec 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the variable names here following a current convention, or can we ditch the abbreviations to make them more descriptive?

@VictorBezak
Copy link
Contributor Author

VictorBezak commented Dec 28, 2022

Tremendous work @filipesantiagoAM . Thanks for all of the guidance @archmoj

src/plots/cartesian/axes.js Outdated Show resolved Hide resolved
src/plots/cartesian/axes.js Outdated Show resolved Hide resolved
src/plots/cartesian/axes.js Outdated Show resolved Hide resolved
var objR = axes.tickText(ax, valR);
var obj = axes.tickText(ax, vali);
obj.text = objR.text;

Copy link
Contributor

@archmoj archmoj Jan 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now to be more accurate about the position of labels and ticks lets simplify this part
from:

            var objR = axes.tickText(ax, valR);
            var obj = axes.tickText(ax, vali);
            obj.text = objR.text;

to:

            var obj = axes.tickText(ax, valR);

Copy link
Contributor

@filipesantiagoAM filipesantiagoAM Jan 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this change, the scroll behaviour is not perfect. It flicks when we try to scroll. Should I commit the changes?

Copy link
Contributor

@archmoj archmoj Jan 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes please commit the change. One may argue that having a more accurate static graph is more important.
After that to reduce the flicks we may end up reducing the deltas from 0.2 to 0.15 or even 0.1 here:

            var val1 = ax.p2l(pos - 0.1);
            var val2 = ax.p2l(pos + 0.1);

Copy link
Contributor

@alexcjohnson alexcjohnson Jan 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What exactly do you mean by "it flicks"? Yes, the static graph needs to be accurate, but can't we get that and clean scroll behavior simultaneously?

Copy link
Contributor

@filipesantiagoAM filipesantiagoAM Jan 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

            var val1 = ax.p2l(pos - 0.1);
            var val2 = ax.p2l(pos + 0.1);

@alexcjohnson This fixes the "flicks".
@archmoj Clean and smooth now.

src/plots/cartesian/axes.js Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants