Skip to content

Commit

Permalink
feat(ripple): support multi-touch (#12643)
Browse files Browse the repository at this point in the history
Currently when using multi-touch on a ripple trigger, the ripple will keep firing from the first touch position (e.g. putting one finger down and then tapping with another). These changes will fire off a ripple for each individual touch.
  • Loading branch information
crisbeto authored and jelbourn committed Aug 21, 2018
1 parent 3b70d20 commit 8fdc2cf
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 4 deletions.
3 changes: 2 additions & 1 deletion src/cdk/testing/event-objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ export function createTouchEvent(type: string, pageX = 0, pageY = 0) {
// the touch details.
Object.defineProperties(event, {
touches: {value: [touchDetails]},
targetTouches: {value: [touchDetails]}
targetTouches: {value: [touchDetails]},
changedTouches: {value: [touchDetails]}
});

return event;
Expand Down
9 changes: 7 additions & 2 deletions src/lib/core/ripple/ripple-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,13 @@ export class RippleRenderer {
this._lastTouchStartEvent = Date.now();
this._isPointerDown = true;

this.fadeInRipple(
event.touches[0].clientX, event.touches[0].clientY, this._target.rippleConfig);
// Use `changedTouches` so we skip any touches where the user put
// their finger down, but used another finger to tap the element again.
const touches = event.changedTouches;

for (let i = 0; i < touches.length; i++) {
this.fadeInRipple(touches[i].clientX, touches[i].clientY, this._target.rippleConfig);
}
}
}

Expand Down
33 changes: 32 additions & 1 deletion src/lib/core/ripple/ripple.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import {TestBed, ComponentFixture, fakeAsync, tick, inject} from '@angular/core/testing';
import {Component, ViewChild} from '@angular/core';
import {Platform} from '@angular/cdk/platform';
import {dispatchMouseEvent, dispatchTouchEvent} from '@angular/cdk/testing';
import {
dispatchEvent,
createTouchEvent,
dispatchMouseEvent,
dispatchTouchEvent,
} from '@angular/cdk/testing';
import {defaultRippleAnimationConfig, RippleAnimationConfig} from './ripple-renderer';
import {
MatRipple, MatRippleModule, MAT_RIPPLE_GLOBAL_OPTIONS, RippleState, RippleGlobalOptions
Expand Down Expand Up @@ -121,6 +126,32 @@ describe('MatRipple', () => {
expect(rippleTarget.querySelectorAll('.mat-ripple-element').length).toBe(0);
}));

it('should launch multiple ripples for multi-touch', fakeAsync(() => {
const touchEvent = createTouchEvent('touchstart');

Object.defineProperties(touchEvent, {
changedTouches: {
value: [
{pageX: 0, pageY: 0},
{pageX: 10, pageY: 10},
{pageX: 20, pageY: 20}
]
}
});

dispatchEvent(rippleTarget, touchEvent);
expect(rippleTarget.querySelectorAll('.mat-ripple-element').length).toBe(3);

tick(enterDuration);
expect(rippleTarget.querySelectorAll('.mat-ripple-element').length).toBe(3);

dispatchTouchEvent(rippleTarget, 'touchend');

tick(exitDuration);

expect(rippleTarget.querySelectorAll('.mat-ripple-element').length).toBe(0);
}));

it('should ignore synthetic mouse events after touchstart', () => fakeAsync(() => {
dispatchTouchEvent(rippleTarget, 'touchstart');
dispatchTouchEvent(rippleTarget, 'mousedown');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
width: 300px;
height: 300px;
line-height: 300px;
-webkit-user-drag: none;
-webkit-tap-highlight-color: transparent;
}

/** Styles to make the demo look better. */
Expand Down

0 comments on commit 8fdc2cf

Please sign in to comment.