Compare commits

...

8 Commits

Author SHA1 Message Date
Liam DeBeasi
926b119231 remove old lines 2019-11-18 15:03:42 -05:00
Liam DeBeasi
256c7de469 only fire pressUp if press was fired; allow overriding of other gesture params 2019-11-18 15:02:38 -05:00
Liam DeBeasi
b7b5b94cce add angular integration 2019-11-12 11:39:21 -05:00
Liam DeBeasi
5e1e883585 sync with master 2019-11-12 11:33:42 -05:00
Liam DeBeasi
ad747b05f1 add press up handler 2019-11-07 15:20:49 -05:00
Liam DeBeasi
3b52074a10 fix typo 2019-11-07 15:17:26 -05:00
Liam DeBeasi
9eac7266a0 Fix 2019-11-07 15:04:18 -05:00
Liam DeBeasi
12a4c974b4 add press recognizer 2019-11-07 15:03:05 -05:00
6 changed files with 246 additions and 1 deletions

View File

@@ -1,5 +1,5 @@
import { Injectable } from '@angular/core';
import { Gesture, GestureConfig, createGesture } from '@ionic/core';
import { Gesture, GestureConfig, PressRecognizerOptions, createGesture, createPressRecognizer } from '@ionic/core';
@Injectable({
providedIn: 'root',
@@ -11,4 +11,11 @@ export class GestureController {
create(opts: GestureConfig): Gesture {
return createGesture(opts);
}
/**
* Create a new Press recognizer gesture
*/
pressRecognizer(opts: PressRecognizerOptions): Gesture {
return createPressRecognizer(opts);
}
}

View File

@@ -3,6 +3,8 @@ import 'ionicons';
export { createAnimation } from './utils/animation/animation';
export { getTimeGivenProgression } from './utils/animation/cubic-bezier';
export { createGesture } from './utils/gesture';
export { createPressRecognizer } from './utils/gesture/recognizers/press';
export { isPlatform, Platforms, getPlatforms } from './utils/platform';
export * from './utils/config';

View File

@@ -35,6 +35,7 @@ export { Animation, AnimationBuilder } from './utils/animation/animation-interfa
export * from './utils/overlays-interface';
export * from './global/config';
export { Gesture, GestureConfig, GestureDetail } from './utils/gesture';
export { PressRecognizerOptions } from './utils/gesture/recognizers/press';
export type TextFieldTypes = 'date' | 'email' | 'number' | 'password' | 'search' | 'tel' | 'text' | 'url' | 'time';
export type Side = 'start' | 'end';

View File

@@ -0,0 +1,91 @@
import { GestureConfig, GestureDetail, createGesture } from '../index';
export interface PressRecognizerOptions extends GestureConfig {
/**
* How long the user must press the
* element before onPressHandler is fired.
*/
time: number;
/**
* The maximum amount of movement on the x and y
* axes that is allowed and still have onPressHandler fire.
*/
maxThreshold: number;
/**
* Fired when the long press occurs.
*/
onPressHandler?: () => void;
/**
* Fired when the pointer is lifted.
*/
onPressUpHandler?: () => void;
}
export const createPressRecognizer = (opts: PressRecognizerOptions) => {
const THRESHOLD = opts.maxThreshold || 10;
let timeout: any;
let pressed = false;
const onStart = (detail: GestureDetail) => {
if (opts.onStart) {
opts.onStart(detail);
}
clearGestureTimeout();
timeout = setTimeout(() => {
if (opts.onPressHandler) {
opts.onPressHandler();
}
pressed = true;
clearGestureTimeout();
}, opts.time || 500);
};
const onMove = (detail: GestureDetail) => {
if (opts.onMove) {
opts.onMove(detail);
}
if (Math.abs(detail.deltaX) + Math.abs(detail.deltaY) <= THRESHOLD) {
return;
}
clearGestureTimeout();
};
const onEnd = (detail: GestureDetail) => {
if (opts.onEnd) {
opts.onEnd(detail);
}
if (!pressed) { return; }
if (opts.onPressUpHandler) {
opts.onPressUpHandler();
}
pressed = false;
clearGestureTimeout();
};
const clearGestureTimeout = () => {
if (timeout) {
clearTimeout(timeout);
timeout = undefined;
}
};
return createGesture({
...opts,
gestureName: opts.gestureName || 'press',
threshold: opts.threshold || 0,
onStart,
onMove,
onEnd,
});
};

View File

@@ -0,0 +1,77 @@
import { newE2EPage } from '@stencil/core/testing';
test(`gesture: press`, async () => {
const page = await newE2EPage({ url: '/src/utils/gesture/recognizers/tests/press' });
const screenshotCompares = [];
screenshotCompares.push(await page.compareScreenshot());
const square = await page.$('.square');
const { x, y } = await coords(square);
page.mouse.move(x, y);
page.mouse.down();
await page.waitFor(300);
expect(await page.find('.square')).toHaveClass('pressed');
page.mouse.up();
expect(await page.find('.square')).toHaveClass('pressedUp');
screenshotCompares.push(await page.compareScreenshot('end press'));
for (const screenshotCompare of screenshotCompares) {
expect(screenshotCompare).toMatchScreenshot();
}
});
test(`gesture: press:short press`, async () => {
const page = await newE2EPage({ url: '/src/utils/gesture/recognizers/tests/press' });
const screenshotCompares = [];
screenshotCompares.push(await page.compareScreenshot());
const square = await page.$('.square');
const { x, y } = await coords(square);
page.mouse.move(x, y);
page.mouse.down();
await page.waitFor(50);
page.mouse.up();
const squareAgain = await page.find('.square');
expect(squareAgain).not.toHaveClass('pressed');
expect(squareAgain).not.toHaveClass('pressedUp');
screenshotCompares.push(await page.compareScreenshot('end press'));
for (const screenshotCompare of screenshotCompares) {
expect(screenshotCompare).toMatchScreenshot();
}
});
test(`gesture: press:click`, async () => {
const page = await newE2EPage({ url: '/src/utils/gesture/recognizers/tests/press' });
const screenshotCompares = [];
screenshotCompares.push(await page.compareScreenshot());
await page.click('.square');
const square = await page.find('.square');
expect(square).not.toHaveClass('pressed');
expect(square).not.toHaveClass('pressedUp');
screenshotCompares.push(await page.compareScreenshot('end press'));
for (const screenshotCompare of screenshotCompares) {
expect(screenshotCompare).toMatchScreenshot();
}
});
const coords = async el => {
const box = await el.boundingBox();
return {
x: Math.floor(box.x + (box.width / 2)),
y: Math.floor(box.y + (box.height / 2))
};
};

View File

@@ -0,0 +1,67 @@
<!DOCTYPE html>
<html dir="ltr">
<head>
<meta charset="UTF-8">
<title>Gesture - Press</title>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link href="../../../../../../css/ionic.bundle.css" rel="stylesheet">
<link href="../../../../../../scripts/testing/styles.css" rel="stylesheet">
<script src="../../../../../../scripts/testing/scripts.js"></script>
<script nomodule src="../../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../../dist/ionic/ionic.esm.js"></script>
<script type="module">
import { createPressRecognizer } from '../../../../../dist/ionic/index.esm.js';
const square = document.querySelector('.square');
const pressRecognizer = createPressRecognizer({
el: square,
time: 251,
minThreshold: 10,
onStart: () => square.classList.remove('pressedUp'),
onPressHandler: () => square.classList.toggle('pressed'),
onPressUpHandler: () => square.classList.add('pressedUp')
});
pressRecognizer.enable(true);
</script>
<style>
.square {
width: 100px;
height: 100px;
background: rgba(255, 0, 0, 0.5);
text-align: center;
line-height: 100px;
margin-left: 25px;
margin-top: 25px;
transition: 0.2s all ease-in-out;
cursor: pointer;
}
.pressed {
transform: scale(1.5);
background: rgba(0, 255, 0, 0.5);
}
</style>
</head>
<body>
<ion-app>
<ion-header>
<ion-toolbar>
<ion-title>Gesture - Press</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<div class="ion-padding">
<div class="square">Hello</div>
</div>
</ion-content>
</ion-app>
</body>
</html>