mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
feat(ripple): support multi-touch (#12643)
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.
This commit is contained in:
committed by
Jeremy Elbourn
parent
3b70d2093f
commit
8fdc2cfca2
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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');
|
||||
|
||||
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user