in src/cdk/drag-drop/drop-list-ref.ts [583:648]
_startScrollingIfNecessary(pointerX: number, pointerY: number) {
if (this.autoScrollDisabled) {
return;
}
let scrollNode: HTMLElement | Window | undefined;
let verticalScrollDirection = AutoScrollVerticalDirection.NONE;
let horizontalScrollDirection = AutoScrollHorizontalDirection.NONE;
// Check whether we should start scrolling any of the parent containers.
this._parentPositions.positions.forEach((position, element) => {
// We have special handling for the `document` below. Also this would be
// nicer with a for...of loop, but it requires changing a compiler flag.
if (element === this._document || !position.clientRect || scrollNode) {
return;
}
if (
isPointerNearClientRect(position.clientRect, DROP_PROXIMITY_THRESHOLD, pointerX, pointerY)
) {
[verticalScrollDirection, horizontalScrollDirection] = getElementScrollDirections(
element as HTMLElement,
position.clientRect,
pointerX,
pointerY,
);
if (verticalScrollDirection || horizontalScrollDirection) {
scrollNode = element as HTMLElement;
}
}
});
// Otherwise check if we can start scrolling the viewport.
if (!verticalScrollDirection && !horizontalScrollDirection) {
const {width, height} = this._viewportRuler.getViewportSize();
const clientRect = {
width,
height,
top: 0,
right: width,
bottom: height,
left: 0,
} as ClientRect;
verticalScrollDirection = getVerticalScrollDirection(clientRect, pointerY);
horizontalScrollDirection = getHorizontalScrollDirection(clientRect, pointerX);
scrollNode = window;
}
if (
scrollNode &&
(verticalScrollDirection !== this._verticalScrollDirection ||
horizontalScrollDirection !== this._horizontalScrollDirection ||
scrollNode !== this._scrollNode)
) {
this._verticalScrollDirection = verticalScrollDirection;
this._horizontalScrollDirection = horizontalScrollDirection;
this._scrollNode = scrollNode;
if ((verticalScrollDirection || horizontalScrollDirection) && scrollNode) {
this._ngZone.runOutsideAngular(this._startScrollInterval);
} else {
this._stopScrolling();
}
}
}