Skip to content

Commit df4f002

Browse files
committed
rewrite offsets to the end of the rendered content as offsets to the
start
1 parent 97d623b commit df4f002

File tree

2 files changed

+34
-18
lines changed

2 files changed

+34
-18
lines changed

src/cdk-experimental/scrolling/auto-size-virtual-scroll.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ export class AutoSizeVirtualScrollStrategy implements VirtualScrollStrategy {
247247
*/
248248
private _checkRenderedContentSize() {
249249
const viewport = this._viewport!;
250-
this._lastRenderedContentOffset = viewport.measureRenderedContentOffset();
250+
this._lastRenderedContentOffset = viewport.getOffsetToRenderedContentStart()!;
251251
this._lastRenderedContentSize = viewport.measureRenderedContentSize();
252252
this._averager.addSample(viewport.getRenderedRange(), this._lastRenderedContentSize);
253253
this._updateTotalContentSize(this._lastRenderedContentSize);

src/cdk-experimental/scrolling/virtual-scroll-viewport.ts

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,15 @@ export class CdkVirtualScrollViewport implements DoCheck, OnInit, OnDestroy {
8686
/** the currently attached CdkVirtualForOf. */
8787
private _forOf: CdkVirtualForOf<any> | null;
8888

89+
/** The last rendered content offset that was set. */
90+
private _renderedContentOffset = 0;
91+
92+
/**
93+
* Whether the last rendered content offset was to the end of the content (and therefore needs to
94+
* be rewritten as an offset to the start of the content).
95+
*/
96+
private _renderedContentOffsetNeedsRewrite = false;
97+
8998
constructor(public elementRef: ElementRef, private _changeDetectorRef: ChangeDetectorRef,
9099
private _ngZone: NgZone, private _sanitizer: DomSanitizer,
91100
@Inject(VIRTUAL_SCROLL_STRATEGY) private _scrollStrategy: VirtualScrollStrategy) {}
@@ -204,21 +213,43 @@ export class CdkVirtualScrollViewport implements DoCheck, OnInit, OnDestroy {
204213
// viewport.setRenderedContentOffset(...);
205214
//
206215
// The call to `onContentRendered` will happen after all of the updates have been applied.
207-
Promise.resolve().then(() => this._scrollStrategy.onContentRendered());
216+
Promise.resolve().then(() => {
217+
// If the rendered content offset was specified as an offset to the end of the content,
218+
// rewrite it as an offset to the start of the content.
219+
if (this._renderedContentOffsetNeedsRewrite) {
220+
this._renderedContentOffset -= this.measureRenderedContentSize();
221+
this._renderedContentOffsetNeedsRewrite = false;
222+
this.setRenderedContentOffset(this._renderedContentOffset);
223+
}
224+
225+
this._scrollStrategy.onContentRendered();
226+
});
208227
}));
209228
});
210229
}
211230
}
212231

213-
/** Sets the offset of the rendered portion of the data from the start (in pixels). */
232+
/**
233+
* Gets the offset from the start of the viewport to the start of the rendered data (in pixels).
234+
*/
235+
getOffsetToRenderedContentStart(): number | null {
236+
return this._renderedContentOffsetNeedsRewrite ? null: this._renderedContentOffset;
237+
}
238+
239+
/**
240+
* Sets the offset from the start of the viewport to either the start or end of the rendered data
241+
* (in pixels).
242+
*/
214243
setRenderedContentOffset(offset: number, to: 'to-start' | 'to-end' = 'to-start') {
215244
const axis = this.orientation === 'horizontal' ? 'X' : 'Y';
216245
let transform = `translate${axis}(${Number(offset)}px)`;
246+
this._renderedContentOffset = offset;
217247
if (to === 'to-end') {
218248
// TODO(mmalerba): The viewport should rewrite this as a `to-start` offset on the next render
219249
// cycle. Otherwise elements will appear to expand in the wrong direction (e.g.
220250
// `mat-expansion-panel` would expand upward).
221251
transform += ` translate${axis}(-100%)`;
252+
this._renderedContentOffsetNeedsRewrite = true;
222253
}
223254
if (this._renderedContentTransform != transform) {
224255
// Re-enter the Angular zone so we can mark for change detection.
@@ -253,21 +284,6 @@ export class CdkVirtualScrollViewport implements DoCheck, OnInit, OnDestroy {
253284
return this.orientation === 'horizontal' ? contentEl.offsetWidth : contentEl.offsetHeight;
254285
}
255286

256-
// TODO(mmalerba): Try to do this in a way that's less bad for performance. (The bad part here is
257-
// that we have to measure the viewport which is not absolutely positioned.)
258-
/** Measure the offset from the start of the viewport to the start of the rendered content. */
259-
measureRenderedContentOffset(): number {
260-
const viewportEl = this.elementRef.nativeElement;
261-
const contentEl = this._contentWrapper.nativeElement;
262-
if (this.orientation === 'horizontal') {
263-
return contentEl.getBoundingClientRect().left + viewportEl.scrollLeft -
264-
viewportEl.getBoundingClientRect().left - viewportEl.clientLeft;
265-
} else {
266-
return contentEl.getBoundingClientRect().top + viewportEl.scrollTop -
267-
viewportEl.getBoundingClientRect().top - viewportEl.clientTop;
268-
}
269-
}
270-
271287
/**
272288
* Measure the total combined size of the given range. Throws if the range includes items that are
273289
* not rendered.

0 commit comments

Comments
 (0)