-
-
Notifications
You must be signed in to change notification settings - Fork 1.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
Add sync option to tickmode
of cartesian axes to sync ticks with overlaying
axis
#6356
Conversation
@alexcjohnson @jackparmer @archmoj |
0c8b15f
to
48e60c2
Compare
@archmoj @alexcjohnson Could you have a look here and give us some feedback please? |
Thanks very much for the PR. |
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. |
…zak/plotly.js into first_poc_tickmode_sync
All good with the checks here.
@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 |
@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 |
src/plots/cartesian/axes.js
Outdated
|
||
// get the tick for the current axis based on position | ||
var vali = ax.p2l(pos); | ||
var val1 = ax.p2l(pos - 0.1); |
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.
@archmoj Now this code makes sense? Now I feel we are at the same position we were before when you suggest this piece of code.
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); obj.text = objR.text;
Suggested change
var val1 = ax.p2l(pos - 0.1); var vali = ax.p2l(pos); var obj = axes.tickText(ax, vali);
I agree we need to improve the roundings but not sure how to do it.
@filipesantiagoAM at this point the logic and behavior looks good to me. |
@@ -28,6 +28,8 @@ module.exports = function handleTickValueDefaults(containerIn, containerOut, coe | |||
|
|||
if(tickmode === 'auto') { | |||
coerce(prefix + 'nticks'); | |||
} else if(tickmode === 'sync') { | |||
coerce('overlaying'); |
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.
@alexcjohnson what do you suggest here?
It looks like we shouldn't use overlaying
attribute "directly":
plotly.js/src/plots/cartesian/layout_attributes.js
Lines 928 to 947 in b03f295
// overlaying: not used directly, just put here for reference | |
// values are false and any other same-letter axis id that's not | |
// itself overlaying anything | |
overlaying: { | |
valType: 'enumerated', | |
values: [ | |
'free', | |
constants.idRegex.x.toString(), | |
constants.idRegex.y.toString() | |
], | |
editType: 'plot', | |
description: [ | |
'If set a same-letter axis id, this axis is overlaid on top of', | |
'the corresponding same-letter axis, with traces and axes visible for both', | |
'axes.', | |
'If *false*, this axis does not overlay any same-letter axes.', | |
'In this case, for axes with overlapping domains only the highest-numbered', | |
'axis will be visible.' | |
].join(' ') | |
}, |
Instead overlaying
is coerced here:
plotly.js/src/plots/cartesian/position_defaults.js
Lines 65 to 70 in b03f295
overlaying = Lib.coerce(containerIn, containerOut, { | |
overlaying: { | |
valType: 'enumerated', | |
values: [false].concat(overlayableAxes), | |
dflt: false | |
} |
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.
If I'm understanding this correctly, the situation we want to avoid is tickmode:'sync'
with no overlaying
. And the challenge is that when we get here, overlaying
hasn't been coerced yet. But @archmoj is right, we can't use the attribute directly and we don't have enough information at this point to coerce it correctly anyway, since we don't know what other axes exist yet.
So what I'd suggest is to leave that block out here, but fix it when we DO have enough information to do that - right after that spot @archmoj pointed to where we coerce overlaying
, there's this block:
if(!overlaying) { |
If we get in there with tickmode === 'sync'
, we should force it to 'auto'
, which means we also need nticks
:
if(containerOut.tickmode === 'sync') {
containerOut.tickmode = 'auto';
coerce('nticks');
}
test/plot-schema.json
Outdated
"editType": "ticks", | ||
"impliedEdits": {}, | ||
"valType": "enumerated", | ||
"values": [ | ||
"auto", | ||
"linear", | ||
"array" | ||
"array", | ||
"sync" |
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.
Perhaps sync shouldn't be added to minor
axes.
If major
ticks are sync, then auto option for minor
ticks on that axis should copy minor ticks from the base axis. No?
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.
Yeah, removing.
@VictorBezak @filipesantiagoAM just playing with this now, it's sooo satisfying to pan/zoom sync axes |
@alexcjohnson @archmoj All good I believe |
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 great! It'll need a draftlog entry, but aside from that I think we're good to go! 💃
@archmoj mentioned to me that the original suggestion I had (over 5 years ago! 🤯) for the new attribute value was 'match overlay'
, and that this perhaps does a better job of self-documenting "oh, to use this I also need to set the overlaying attribute," also that 'sync'
could imply a two-way interaction whereas this is one-way: the main axis sets the tick positions, all overlaying axes just use those.
While I think those arguments make sense, I also see the benefit of 'sync'
: It's shorter and easier to remember (vs 'match overlay'
, or is it 'matches overlaying'
or ... ?) and still, to my eye anyway, fairly intuitive and well-documented by the description. So I'm happy to leave it as is.
tickmode
of cartesian axes to sync ticks with overlaying
axis
tickmode
of cartesian axes to sync ticks with overlaying
axistickmode
of cartesian axes to sync ticks with overlaying
axis
Hi all, I was very glad to see that this longstanding issue was worked through and solved - thanks very much for your work on it! I have tried out the new tickmode='sync' option in a plot with plotly.js release 2.18.0 , but I get "non-rounded" tick values on the y2 axis e.g. 169.4, 145.2 etc See example here & screenshot at end of this post Am I missing something, or is that the intended behaviour at the moment? Thanks! |
@hottwaj that’s correct, making the ticks also round numbers for the synced axis would require adjusting its (auto)range, which was out of scope for this PR. I do like that idea, though I don’t think we want I to to be the default. But we’d gladly accept a PR adding an option to expand the autorange until the tick values are round numbers. With the caveat that in some cases this will not be possible, like syncing axes of different types. |
OK got it, thanks for clarifying - I misunderstood what was being covered here. Great work and thanks for getting this implemented :) |
thanks @VictorBezak !, it is helping so much |
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
tickmode: "sync"
on your 2ndyaxis
that also has propertyoverlaying
set.new_tickmode_sync.json
Things Tested and Working
Not Done Yet