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
Calculate current absolute position of fixed-position elements #5624
Calculate current absolute position of fixed-position elements #5624
Conversation
@@ -172,8 +172,7 @@ export class BaseElement { | |||
* @return {!./layout-rect.LayoutRectDef} | |||
*/ | |||
getLayoutBox() { | |||
return this.element.getResources().getResourceForElement( | |||
this.element).getLayoutBox(); | |||
return this.element.getLayoutBox(); |
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.
is this a DOM api? i think this should be from resources-impl - like how it was before?
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.
It's defined in custom-element.js
. It does exactly this.
LGTM - @dvoytenko do you want to take a pass? |
Yes. Looking. |
@@ -444,9 +444,6 @@ function createBaseCustomElementClass(win) { | |||
this.layout_ = Layout.NODISPLAY; | |||
|
|||
/** @private {number} */ | |||
this.layoutWidth_ = -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.
What's going to happen to this var? I still see it used throughout in this class.
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.
You're looking at an old diff.
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.
No, I think I'm looking at the right one. This appears to be a9808200539a76eb965b6c6f7d0aba79cce8a4e1
commit...
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.
Whoops. Re-added.
@@ -707,6 +704,7 @@ function createBaseCustomElementClass(win) { | |||
this.implementation_.layoutWidth_ = this.layoutWidth_; | |||
} | |||
// TODO(malteubl): Forward for stubbed elements. | |||
// TODO(jridgewell): We should pass the layoutBox down. |
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.
It's passed. Right?
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.
this.implementation_.onLayoutMeasure();
. We should pass it to #onLayoutMeasure
, because a lot of them immediately call #getLayoutBox
.
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.
Ok, that'd be fine, of course. But we'd keep getLayoutBox()
method itself? I made more notes on this below as well. Ideally this would be only size. However, in the meantime, what this API promises is to return "the last measured/known layout box".
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.
But we'd keep getLayoutBox() method itself?
Yup, we need that else where.
Ideally this would be only size.
Yah, just passing { width, height }
would satisfy most all of them. Anyone else could call #getPosition
or whatever we end up calling it.
return this.layoutBox_; | ||
} | ||
const viewport = this.resources_.getViewport(); | ||
return moveLayoutRect(this.layoutBox_, viewport.getScrollLeft(), |
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.
Hmm. This is a bit troublesome. The definition of the getLayoutBox
is that it doesn't change based on the scroll state. We are de-facto changing it here. I'm not sure what downstream issues we maybe expecting from this. The truth is, of course, that fixed element's layout box doesn't change but defined within another (fixed) layer. I think a better option for us would be:
- Modify
overlaps
method to incorporate the knowledge ofisFixed
. We can even rename it asoverlapsViewport
. IMO, this is better b/c this is a more direct API that's only used for the purposes of scheduling. - At this time, propagating
getLayoutBox
is rather dangerous. I don't know who uses it and where. I think it's best to replace this call withgetLayoutSize()
orgetLayoutWidth/Height
pair. I believe most of clients only care about size and not absolute position.
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.
The definition of the getLayoutBox is that it doesn't change based on the scroll state.
I've taken it to mean "give me the absolute position from the origin (0, 0)", which is how everything (until we introduced #isFixed
) treated it. This just fixes the value fixed-position's return.
- Modify overlaps method to incorporate the knowledge of isFixed.
The overlaps stuff is totally superficial to the PR. I need to fix #getLayoutBox
for Flying Carpet, which depends on it returning an absolute position.
I don't know who uses it and where. I think it's best to replace this call with getLayoutSize() or getLayoutWidth/Height pair.
I'd love to see this. Should we wait for the Layers work?
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, it should definitely wait for layers work. Or, alternatively we can do a refactoring pass to clarify this API and remove exposing left/top to clients that don't need it.
I've taken it to mean "give me the absolute position from the origin (0, 0)", which is how everything (until we introduced #isFixed) treated it. This just fixes the value fixed-position's return.
This might be a mis-understanding, but this is not how I read this code. I definitely understand that the current implementation is wrong, but not yet clear that this fixes it.
What does "origin (0, 0)" mean: document origin or viewport origin? From what I see, (assuming we measured the fixed element once at first) if I call this method twice at different scroll positions (e.g. scrollTop=100 and 200) this method will now return different results. I'm not sure if that'd improve things.
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.
Or, alternatively we can do a refactoring pass to clarify this API and remove exposing left/top to clients that don't need it.
That works.
What does "origin (0, 0)" mean: document origin or viewport origin?
The top left corner of the document, not the viewport.
if I call this method twice at different scroll positions (e.g. scrollTop=100 and 200) this method will now return different results.
Exactly. Because the fixed-position has "moved" relative to the origin. Because fixed-position's are fixed relative to the viewport (usually), and the viewport moves down the document, so fixed-positions move.
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.
I see. Alright.
@@ -444,9 +444,6 @@ function createBaseCustomElementClass(win) { | |||
this.layout_ = Layout.NODISPLAY; | |||
|
|||
/** @private {number} */ | |||
this.layoutWidth_ = -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.
No, I think I'm looking at the right one. This appears to be a9808200539a76eb965b6c6f7d0aba79cce8a4e1
commit...
@@ -707,6 +704,7 @@ function createBaseCustomElementClass(win) { | |||
this.implementation_.layoutWidth_ = this.layoutWidth_; | |||
} | |||
// TODO(malteubl): Forward for stubbed elements. | |||
// TODO(jridgewell): We should pass the layoutBox down. |
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.
Ok, that'd be fine, of course. But we'd keep getLayoutBox()
method itself? I made more notes on this below as well. Ideally this would be only size. However, in the meantime, what this API promises is to return "the last measured/known layout box".
2a2132c
to
09c2437
Compare
This makes the Resource’s `layoutBox` aware of fixed-position behavior. We now store the _relative_ position to the viewport for fixed-positions. When the element requests it’s current `layoutBox`, we’ll return the absolute position from (0, 0) based on the current `scrollTop` and `scrollLeft`.
09c2437
to
d8b2b48
Compare
a252937
to
3869f24
Compare
@dvoytenko: Can you take one last look, added two more commits for testing. |
LGTM |
…oject#5624) * tmp * Make layoutBox rects aware of fixed position movement This makes the Resource’s `layoutBox` aware of fixed-position behavior. We now store the _relative_ position to the viewport for fixed-positions. When the element requests it’s current `layoutBox`, we’ll return the absolute position from (0, 0) based on the current `scrollTop` and `scrollLeft`. * Fix out of order assignment * Re-add #layoutWidth. Accidental deletion. * Fix const assignments * Fix calcTaskScore_ tests for fixeds * Fix setting initialLayoutBox_
…oject#5624) * tmp * Make layoutBox rects aware of fixed position movement This makes the Resource’s `layoutBox` aware of fixed-position behavior. We now store the _relative_ position to the viewport for fixed-positions. When the element requests it’s current `layoutBox`, we’ll return the absolute position from (0, 0) based on the current `scrollTop` and `scrollLeft`. * Fix out of order assignment * Re-add #layoutWidth. Accidental deletion. * Fix const assignments * Fix calcTaskScore_ tests for fixeds * Fix setting initialLayoutBox_
Currently, Resources caches the absolute position (
layoutBox
'stop
andbottom
). This works perfectly for the majority of elements, since they never move absolutely.But fixed-position elements are different. They are positioned relative to the viewport, and the viewport moves. So, fixed-positions "move" absolutely. This change makes it so that we cache the relative positions of fixed-positions (to the viewport). When we later ask for the element's
layoutBox
, we'll calculate the "absolute" position by adding in the currentscrollTop
andscrollLeft
. This is exactly the same as what I'm doing for ad'slayoutBox
.Part 2 (and hopefully the final) of #5149.
/cc @jasti.