Skip to content

Commit 7714a5c

Browse files
crisbetokara
authored andcommitted
fix(ripple): use element coordinates instead of page coordinates (#7446)
Fixes #7436.
1 parent f40a7cc commit 7714a5c

File tree

5 files changed

+26
-36
lines changed

5 files changed

+26
-36
lines changed

src/lib/core/ripple/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import {NgModule} from '@angular/core';
10-
import {ScrollDispatchModule, VIEWPORT_RULER_PROVIDER} from '@angular/cdk/scrolling';
10+
import {ScrollDispatchModule} from '@angular/cdk/scrolling';
1111
import {PlatformModule} from '@angular/cdk/platform';
1212
import {MatCommonModule} from '../common-behaviors/common-module';
1313
import {MatRipple} from './ripple';
@@ -20,6 +20,5 @@ export {RippleConfig, RIPPLE_FADE_IN_DURATION, RIPPLE_FADE_OUT_DURATION} from '.
2020
imports: [MatCommonModule, PlatformModule, ScrollDispatchModule],
2121
exports: [MatRipple, MatCommonModule],
2222
declarations: [MatRipple],
23-
providers: [VIEWPORT_RULER_PROVIDER],
2423
})
2524
export class MatRippleModule {}

src/lib/core/ripple/ripple-renderer.ts

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
import {ElementRef, NgZone} from '@angular/core';
1010
import {Platform} from '@angular/cdk/platform';
11-
import {ViewportRuler} from '@angular/cdk/scrolling';
1211
import {RippleRef, RippleState} from './ripple-ref';
1312

1413

@@ -56,11 +55,7 @@ export class RippleRenderer {
5655
/** Whether mouse ripples should be created or not. */
5756
rippleDisabled: boolean = false;
5857

59-
constructor(
60-
elementRef: ElementRef,
61-
private _ngZone: NgZone,
62-
private _ruler: ViewportRuler,
63-
platform: Platform) {
58+
constructor(elementRef: ElementRef, private _ngZone: NgZone, platform: Platform) {
6459
// Only do anything if we're on the browser.
6560
if (platform.isBrowser) {
6661
this._containerElement = elementRef.nativeElement;
@@ -79,27 +74,26 @@ export class RippleRenderer {
7974
}
8075
}
8176

82-
/** Fades in a ripple at the given coordinates. */
83-
fadeInRipple(pageX: number, pageY: number, config: RippleConfig = {}): RippleRef {
84-
let containerRect = this._containerElement.getBoundingClientRect();
77+
/**
78+
* Fades in a ripple at the given coordinates.
79+
* @param x Coordinate within the element, along the X axis at which to start the ripple.
80+
* @param Y Coordinate within the element, along the Y axis at which to start the ripple.
81+
* @param config Extra ripple options.
82+
*/
83+
fadeInRipple(x: number, y: number, config: RippleConfig = {}): RippleRef {
84+
const containerRect = this._containerElement.getBoundingClientRect();
8585

8686
if (config.centered) {
87-
pageX = containerRect.left + containerRect.width / 2;
88-
pageY = containerRect.top + containerRect.height / 2;
89-
} else {
90-
// Subtract scroll values from the coordinates because calculations below
91-
// are always relative to the viewport rectangle.
92-
let scrollPosition = this._ruler.getViewportScrollPosition();
93-
pageX -= scrollPosition.left;
94-
pageY -= scrollPosition.top;
87+
x = containerRect.left + containerRect.width / 2;
88+
y = containerRect.top + containerRect.height / 2;
9589
}
9690

97-
let radius = config.radius || distanceToFurthestCorner(pageX, pageY, containerRect);
98-
let duration = RIPPLE_FADE_IN_DURATION * (1 / (config.speedFactor || 1));
99-
let offsetX = pageX - containerRect.left;
100-
let offsetY = pageY - containerRect.top;
91+
const radius = config.radius || distanceToFurthestCorner(x, y, containerRect);
92+
const duration = RIPPLE_FADE_IN_DURATION * (1 / (config.speedFactor || 1));
93+
const offsetX = x - containerRect.left;
94+
const offsetY = y - containerRect.top;
10195

102-
let ripple = document.createElement('div');
96+
const ripple = document.createElement('div');
10397
ripple.classList.add('mat-ripple-element');
10498

10599
ripple.style.left = `${offsetX - radius}px`;
@@ -189,7 +183,7 @@ export class RippleRenderer {
189183
private onMousedown(event: MouseEvent) {
190184
if (!this.rippleDisabled) {
191185
this._isPointerDown = true;
192-
this.fadeInRipple(event.pageX, event.pageY, this.rippleConfig);
186+
this.fadeInRipple(event.clientX, event.clientY, this.rippleConfig);
193187
}
194188
}
195189

@@ -215,9 +209,9 @@ export class RippleRenderer {
215209
/** Function being called whenever the trigger is being touched. */
216210
private onTouchstart(event: TouchEvent) {
217211
if (!this.rippleDisabled) {
218-
const {pageX, pageY} = event.touches[0];
212+
const {clientX, clientY} = event.touches[0];
219213
this._isPointerDown = true;
220-
this.fadeInRipple(pageX, pageY, this.rippleConfig);
214+
this.fadeInRipple(clientX, clientY, this.rippleConfig);
221215
}
222216
}
223217

src/lib/core/ripple/ripple.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {TestBed, ComponentFixture, fakeAsync, tick, inject} from '@angular/core/testing';
22
import {Component, ViewChild} from '@angular/core';
33
import {Platform} from '@angular/cdk/platform';
4-
import {ViewportRuler} from '@angular/cdk/scrolling';
4+
import {ViewportRuler, VIEWPORT_RULER_PROVIDER} from '@angular/cdk/scrolling';
55
import {dispatchMouseEvent, dispatchTouchEvent} from '@angular/cdk/testing';
66
import {RIPPLE_FADE_OUT_DURATION, RIPPLE_FADE_IN_DURATION} from './ripple-renderer';
77
import {
@@ -24,6 +24,7 @@ describe('MatRipple', () => {
2424
beforeEach(() => {
2525
TestBed.configureTestingModule({
2626
imports: [MatRippleModule],
27+
providers: [VIEWPORT_RULER_PROVIDER],
2728
declarations: [
2829
BasicRippleContainer,
2930
RippleContainerWithInputBindings,

src/lib/core/ripple/ripple.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import {
1818
InjectionToken,
1919
Optional,
2020
} from '@angular/core';
21-
import {ViewportRuler} from '@angular/cdk/scrolling';
2221
import {Platform} from '@angular/cdk/platform';
2322
import {RippleConfig, RippleRenderer} from './ripple-renderer';
2423
import {RippleRef} from './ripple-ref';
@@ -91,11 +90,10 @@ export class MatRipple implements OnChanges, OnDestroy {
9190
constructor(
9291
elementRef: ElementRef,
9392
ngZone: NgZone,
94-
ruler: ViewportRuler,
9593
platform: Platform,
9694
@Optional() @Inject(MAT_RIPPLE_GLOBAL_OPTIONS) globalOptions: RippleGlobalOptions
9795
) {
98-
this._rippleRenderer = new RippleRenderer(elementRef, ngZone, ruler, platform);
96+
this._rippleRenderer = new RippleRenderer(elementRef, ngZone, platform);
9997
this._globalOptions = globalOptions ? globalOptions : {};
10098

10199
this._updateRippleRenderer();
@@ -115,8 +113,8 @@ export class MatRipple implements OnChanges, OnDestroy {
115113
}
116114

117115
/** Launches a manual ripple at the specified position. */
118-
launch(pageX: number, pageY: number, config = this.rippleConfig): RippleRef {
119-
return this._rippleRenderer.fadeInRipple(pageX, pageY, config);
116+
launch(x: number, y: number, config = this.rippleConfig): RippleRef {
117+
return this._rippleRenderer.fadeInRipple(x, y, config);
120118
}
121119

122120
/** Fades out all currently showing ripple elements. */

src/lib/tabs/tab-nav-bar/tab-nav-bar.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {Directionality} from '@angular/cdk/bidi';
1010
import {coerceBooleanProperty} from '@angular/cdk/coercion';
1111
import {Platform} from '@angular/cdk/platform';
1212
import {auditTime, takeUntil} from '@angular/cdk/rxjs';
13-
import {ViewportRuler} from '@angular/cdk/scrolling';
1413
import {
1514
AfterContentInit,
1615
ChangeDetectionStrategy,
@@ -225,14 +224,13 @@ export class MatTabLink extends _MatTabLinkMixinBase implements OnDestroy, CanDi
225224
constructor(private _tabNavBar: MatTabNav,
226225
private _elementRef: ElementRef,
227226
ngZone: NgZone,
228-
ruler: ViewportRuler,
229227
platform: Platform,
230228
@Optional() @Inject(MAT_RIPPLE_GLOBAL_OPTIONS) globalOptions: RippleGlobalOptions) {
231229
super();
232230

233231
// Manually create a ripple instance that uses the tab link element as trigger element.
234232
// Notice that the lifecycle hooks for the ripple config won't be called anymore.
235-
this._tabLinkRipple = new MatRipple(_elementRef, ngZone, ruler, platform, globalOptions);
233+
this._tabLinkRipple = new MatRipple(_elementRef, ngZone, platform, globalOptions);
236234
}
237235

238236
ngOnDestroy() {

0 commit comments

Comments
 (0)