Skip to content

Commit 1acc6e4

Browse files
mapsandappsthetaPC
andauthored
docs(animation): add playground example for double-click gesture (#3042)
Co-authored-by: dillionmegida < [email protected]> Co-authored-by: Maria Hutt <[email protected]>
1 parent 4d8f605 commit 1acc6e4

File tree

11 files changed

+349
-170
lines changed

11 files changed

+349
-170
lines changed

docs/utilities/gestures.md

Lines changed: 3 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -272,177 +272,11 @@ In this example, our app listens for gestures on the `.rectangle` element. When
272272

273273
## Double Click Gesture
274274

275-
### Usage
276-
277-
````mdx-code-block
278-
<Tabs
279-
groupId="framework"
280-
defaultValue="javascript"
281-
values={[
282-
{ value: 'javascript', label: 'JavaScript' },
283-
{ value: 'angular', label: 'Angular' },
284-
{ value: 'react', label: 'React' },
285-
{ value: 'vue', label: 'Vue' },
286-
]
287-
}>
288-
<TabItem value="javascript">
289-
290-
```javascript
291-
const backgrounds = ['rgba(0, 0, 255, 0.5)', 'rgba(0, 255, 0.5)', 'rgba(255, 0, 0, 0.5)', 'rgba(255, 255, 0, 0.5)', 'rgba(255, 0, 255, 0.5)', 'rgba(0, 255, 255, 0.5)'];
292-
const DOUBLE_CLICK_THRESHOLD = 500;
293-
const rectangle = document.querySelector('.rectangle');
294-
const gesture = createGesture({
295-
el: rectangle,
296-
threshold: 0,
297-
onStart: () => { onStart(); }
298-
});
299-
300-
gesture.enable();
301-
302-
let lastOnStart = 0;
303-
let currentColor = 'rgba(0, 0, 255, 0.5)';
304-
305-
const onStart = () => {
306-
const now = Date.now();
307-
308-
if (Math.abs(now - lastOnStart) <= DOUBLE_CLICK_THRESHOLD) {
309-
rectangle.style.setProperty('background', getRandomBackground());
310-
lastOnStart = 0;
311-
} else {
312-
lastOnStart = now;
313-
}
314-
}
315-
316-
const getRandomBackground = () => {
317-
const options = backgrounds.filter(bg => bg !== currentColor);
318-
currentColor = options[Math.floor(Math.random() * options.length)];
319-
320-
return currentColor;
321-
}
322-
```
323-
</TabItem>
324-
<TabItem value="angular">
325-
326-
```tsx
327-
@ViewChild('rectangle') rectangle: ElementRef;
328-
329-
private backgrounds: string[] = ['rgba(0, 0, 255, 0.5)', 'rgba(0, 255, 0.5)', 'rgba(255, 0, 0, 0.5)', 'rgba(255, 255, 0, 0.5)', 'rgba(255, 0, 255, 0.5)', 'rgba(0, 255, 255, 0.5)'];
330-
private currentColor: string = 'rgba(0, 0, 255, 0.5)';
331-
private lastOnStart: number = 0;
332-
private DOUBLE_CLICK_THRESHOLD: number = 500;
333-
334-
ngOnInit() {
335-
const gesture = this.gestureCtrl.create({
336-
el: this.rectangle.nativeElement,
337-
threshold: 0,
338-
onStart: () => { this.onStart(); }
339-
});
340-
341-
gesture.enable();
342-
}
343-
344-
private onStart() {
345-
const now = Date.now();
346-
347-
if (Math.abs(now - this.lastOnStart) <= this.DOUBLE_CLICK_THRESHOLD) {
348-
this.rectangle.nativeElement.style.setProperty('background', this.getRandomBackground());
349-
this.lastOnStart = 0;
350-
} else {
351-
this.lastOnStart = now;
352-
}
353-
}
354-
355-
private getRandomBackground() {
356-
const options = this.backgrounds.filter(bg => bg !== this.currentColor);
357-
this.currentColor = options[Math.floor(Math.random() * options.length)];
358-
359-
return this.currentColor;
360-
}
361-
```
362-
</TabItem>
363-
<TabItem value="react">
364-
365-
```javascript
366-
const backgrounds = ['rgba(0, 0, 255, 0.5)', 'rgba(0, 255, 0.5)', 'rgba(255, 0, 0, 0.5)', 'rgba(255, 255, 0, 0.5)', 'rgba(255, 0, 255, 0.5)', 'rgba(0, 255, 255, 0.5)'];
367-
const DOUBLE_CLICK_THRESHOLD = 500;
368-
const rectangle = document.querySelector('.rectangle');
369-
const gesture = createGesture({
370-
el: rectangle,
371-
threshold: 0,
372-
onStart: () => { onStart(); }
373-
});
374-
375-
gesture.enable();
376-
377-
let lastOnStart = 0;
378-
let currentColor = 'rgba(0, 0, 255, 0.5)';
379-
380-
const onStart = () => {
381-
const now = Date.now();
382-
383-
if (Math.abs(now - lastOnStart) <= DOUBLE_CLICK_THRESHOLD) {
384-
rectangle.style.setProperty('background', getRandomBackground());
385-
lastOnStart = 0;
386-
} else {
387-
lastOnStart = now;
388-
}
389-
}
390-
391-
const getRandomBackground = () => {
392-
const options = backgrounds.filter(bg => bg !== currentColor);
393-
currentColor = options[Math.floor(Math.random() * options.length)];
394-
395-
return currentColor;
396-
}
397-
```
398-
</TabItem>
399-
<TabItem value="vue">
400-
401-
```javascript
402-
import { createGesture } from '@ionic/vue';
403-
import { ref } from 'vue';
404-
405-
...
406-
407-
const backgrounds = ['rgba(0, 0, 255, 0.5)', 'rgba(0, 255, 0.5)', 'rgba(255, 0, 0, 0.5)', 'rgba(255, 255, 0, 0.5)', 'rgba(255, 0, 255, 0.5)', 'rgba(0, 255, 255, 0.5)'];
408-
const DOUBLE_CLICK_THRESHOLD = 500;
409-
const rectangleRef = ref();
410-
const gesture = createGesture({
411-
el: rectangleRef.value,
412-
threshold: 0,
413-
onStart: () => { onStart(); }
414-
});
415-
416-
gesture.enable();
417-
418-
let lastOnStart = 0;
419-
let currentColor = 'rgba(0, 0, 255, 0.5)';
420-
421-
const onStart = () => {
422-
const now = Date.now();
423-
424-
if (Math.abs(now - lastOnStart) <= DOUBLE_CLICK_THRESHOLD) {
425-
rectangleRef.value.style.setProperty('background', getRandomBackground());
426-
lastOnStart = 0;
427-
} else {
428-
lastOnStart = now;
429-
}
430-
}
431-
432-
const getRandomBackground = () => {
433-
const options = backgrounds.filter(bg => bg !== currentColor);
434-
currentColor = options[Math.floor(Math.random() * options.length)];
435-
436-
return currentColor;
437-
}
438-
```
439-
</TabItem>
440-
</Tabs>
441-
````
275+
import DoubleClick from '@site/static/usage/v7/gestures/double-click/index.md';
442276

443-
In the example above, we want to be able to detect double clicks on an element. By setting our `threshold` to `0`, we can ensure our gesture object can detect clicks. Additionally, we define a click threshold so that only 2 clicks that occur in quick succession count as a double click.
277+
In the example below, we want to be able to detect double clicks on an element. By setting our `threshold` to `0`, we can ensure our gesture object can detect clicks. Additionally, we define a click threshold so that only 2 clicks that occur in quick succession count as a double click.
444278

445-
<Codepen user="ionic" slug="oNvVEwE" />
279+
<DoubleClick />
446280

447281
## Gesture Animations
448282

static/code/stackblitz/v7/html/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { defineCustomElements } from '@ionic/core/loader';
22

3-
import { createAnimation, loadingController, modalController, pickerController, toastController } from '@ionic/core';
3+
import { createAnimation, createGesture, loadingController, modalController, pickerController, toastController } from '@ionic/core';
44

55
/* Core CSS required for Ionic components to work properly */
66
import '@ionic/core/css/core.css';
@@ -28,3 +28,4 @@ defineCustomElements();
2828
(window as any).pickerController = pickerController;
2929
(window as any).toastController = toastController;
3030
(window as any).createAnimation = createAnimation;
31+
(window as any).createGesture = createGesture;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
```css
2+
ion-card {
3+
transform: translateX(0);
4+
user-select: none;
5+
}
6+
```
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
```html
2+
<ion-card #card>
3+
<ion-card-content>Double click me to move the card.</ion-card-content>
4+
</ion-card>
5+
```
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
```ts
2+
import { Component, ElementRef, ViewChild } from '@angular/core';
3+
import { GestureController, IonCard } from '@ionic/angular';
4+
5+
@Component({
6+
selector: 'app-example',
7+
templateUrl: 'example.component.html',
8+
styleUrls: ['./example.component.css'],
9+
})
10+
export class ExampleComponent {
11+
@ViewChild('card', { read: ElementRef }) card: ElementRef<HTMLIonCardElement>;
12+
13+
private currentOffset: number = 0;
14+
private lastOnStart: number = 0;
15+
private DOUBLE_CLICK_THRESHOLD: number = 500;
16+
17+
constructor(private el: ElementRef, private gestureCtrl: GestureController) {}
18+
19+
ngAfterViewInit() {
20+
const gesture = this.gestureCtrl.create({
21+
el: this.card.nativeElement,
22+
threshold: 0,
23+
onStart: () => this.onStart(),
24+
gestureName: 'double-click',
25+
});
26+
27+
gesture.enable();
28+
}
29+
30+
private onStart() {
31+
const now = Date.now();
32+
33+
if (Math.abs(now - this.lastOnStart) <= this.DOUBLE_CLICK_THRESHOLD) {
34+
this.card.nativeElement.style.setProperty('transform', this.getNewTransform());
35+
this.lastOnStart = 0;
36+
} else {
37+
this.lastOnStart = now;
38+
}
39+
}
40+
41+
private getNewTransform() {
42+
if (this.currentOffset >= 100) {
43+
this.currentOffset = 0;
44+
} else {
45+
this.currentOffset += 20;
46+
}
47+
48+
return `translateX(${this.currentOffset}px)`;
49+
}
50+
}
51+
```
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Double-Click Gestures</title>
7+
<link rel="stylesheet" href="../../../common.css" />
8+
<script src="../../../common.js"></script>
9+
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core@7/dist/ionic/ionic.esm.js"></script>
10+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/core@7/css/ionic.bundle.css" />
11+
12+
<script type="module">
13+
import { createGesture } from 'https://cdn.jsdelivr.net/npm/@ionic/core@7/dist/ionic/index.esm.js';
14+
window.createGesture = createGesture;
15+
16+
const DOUBLE_CLICK_THRESHOLD = 500;
17+
const card = document.querySelector('ion-card');
18+
const gesture = createGesture({
19+
el: card,
20+
threshold: 0,
21+
onStart: () => onStart(),
22+
gestureName: 'double-click',
23+
});
24+
25+
gesture.enable();
26+
27+
let lastOnStart = 0;
28+
let currentOffset = 0;
29+
30+
const onStart = () => {
31+
const now = Date.now();
32+
33+
if (Math.abs(now - lastOnStart) <= DOUBLE_CLICK_THRESHOLD) {
34+
card.style.setProperty('transform', getNewTransform());
35+
lastOnStart = 0;
36+
} else {
37+
lastOnStart = now;
38+
}
39+
};
40+
41+
const getNewTransform = () => {
42+
if (currentOffset >= 100) {
43+
currentOffset = 0;
44+
} else {
45+
currentOffset += 20;
46+
}
47+
48+
return `translateX(${currentOffset}px)`;
49+
};
50+
</script>
51+
52+
<style>
53+
ion-card {
54+
transform: translateX(0);
55+
user-select: none;
56+
}
57+
</style>
58+
</head>
59+
60+
<body>
61+
<ion-content>
62+
<ion-card>
63+
<ion-card-content>Double click me to move the card.</ion-card-content>
64+
</ion-card>
65+
</ion-content>
66+
</body>
67+
</html>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import Playground from '@site/src/components/global/Playground';
2+
3+
import javascript from './javascript.md';
4+
5+
import react_main_tsx from './react/main_tsx.md';
6+
import react_main_css from './react/main_css.md';
7+
8+
import vue from './vue.md';
9+
10+
import angular_example_component_html from './angular/example_component_html.md';
11+
import angular_example_component_ts from './angular/example_component_ts.md';
12+
import angular_example_component_css from './angular/example_component_css.md';
13+
14+
<Playground
15+
version="7"
16+
code={{
17+
javascript,
18+
react: {
19+
files: {
20+
'src/main.tsx': react_main_tsx,
21+
'src/main.css': react_main_css,
22+
},
23+
},
24+
vue,
25+
angular: {
26+
files: {
27+
'src/app/example.component.html': angular_example_component_html,
28+
'src/app/example.component.ts': angular_example_component_ts,
29+
'src/app/example.component.css': angular_example_component_css,
30+
},
31+
},
32+
}}
33+
src="usage/v7/gestures/double-click/demo.html"
34+
/>

0 commit comments

Comments
 (0)