Skip to content

Commit 431cecc

Browse files
docs(animations): add playground for before and after hooks (#3035)
Co-authored-by: dillionmegida <[email protected]>
1 parent fa26dee commit 431cecc

File tree

8 files changed

+320
-109
lines changed

8 files changed

+320
-109
lines changed

docs/utilities/animations.md

Lines changed: 4 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -255,118 +255,13 @@ import Group from '@site/static/usage/v7/animations/group/index.md';
255255

256256
Ionic Animations provides hooks that let you alter an element before an animation runs and after an animation completes. These hooks can be used to perform DOM reads and writes as well as add or remove classes and inline styles.
257257

258-
### Usage
259-
260-
````mdx-code-block
261-
<Tabs
262-
groupId="framework"
263-
defaultValue="javascript"
264-
values={[
265-
{ value: 'javascript', label: 'JavaScript' },
266-
{ value: 'angular', label: 'Angular' },
267-
{ value: 'react', label: 'React' },
268-
{ value: 'vue', label: 'Vue' },
269-
]
270-
}>
271-
<TabItem value="javascript">
272-
273-
```javascript
274-
createAnimation()
275-
.addElement(document.querySelector('.square'))
276-
.duration(2000)
277-
.beforeStyles({
278-
opacity: 0.2
279-
})
280-
.afterStyles({
281-
background: 'rgba(0, 255, 0, 0.5)'
282-
})
283-
.afterClearStyles(['opacity'])
284-
.keyframes([
285-
{ offset: 0, transform: 'scale(1)' },
286-
{ offset: 0.5, transform: 'scale(1.5)' },
287-
{ offset: 1, transform: 'scale(1)' }
288-
])
289-
```
290-
</TabItem>
291-
<TabItem value="angular">
292-
293-
```javascript
294-
this.animationCtrl.create()
295-
.addElement(this.square.nativeElement)
296-
.duration(2000)
297-
.beforeStyles({
298-
opacity: 0.2
299-
})
300-
.afterStyles({
301-
background: 'rgba(0, 255, 0, 0.5)'
302-
})
303-
.afterClearStyles(['opacity'])
304-
.keyframes([
305-
{ offset: 0, transform: 'scale(1)' },
306-
{ offset: 0.5, transform: 'scale(1.5)' },
307-
{ offset: 1, transform: 'scale(1)' }
308-
])
309-
```
310-
</TabItem>
311-
<TabItem value="react">
312-
313-
```tsx
314-
<CreateAnimation
315-
duration={2000}
316-
beforeStyles={{
317-
opacity: 0.2
318-
}}
319-
afterStyles={{
320-
background: 'rgba(0, 255, 0, 0.5)'
321-
}}
322-
afterClearStyles={['opacity']}
323-
keyframes={[
324-
{ offset: 0, transform: 'scale(1)' },
325-
{ offset: 0.5, transform: 'scale(1.5)' },
326-
{ offset: 1, transform: 'scale(1)' }
327-
]}
328-
>
329-
...
330-
</CreateAnimation>
331-
```
332-
</TabItem>
333-
<TabItem value="vue">
334-
335-
```javascript
336-
import { createAnimation } from '@ionic/vue';
337-
import { ref } from 'vue';
338-
339-
...
340-
341-
const squareRef = ref();
342-
343-
...
344-
345-
createAnimation()
346-
.addElement(squareRef.value)
347-
.duration(2000)
348-
.beforeStyles({
349-
opacity: 0.2
350-
})
351-
.afterStyles({
352-
background: 'rgba(0, 255, 0, 0.5)'
353-
})
354-
.afterClearStyles(['opacity'])
355-
.keyframes([
356-
{ offset: 0, transform: 'scale(1)' },
357-
{ offset: 0.5, transform: 'scale(1.5)' },
358-
{ offset: 1, transform: 'scale(1)' }
359-
])
360-
```
361-
</TabItem>
362-
</Tabs>
363-
````
364-
365-
In this example, an inline opacity of 0.2 is set on the `.square` element prior to the animation starting. Once the animation finishes, the background color of the element is set to `rgba(0, 255, 0, 0.5)`, and the inline opacity is cleared.
258+
This example sets an inline filter which inverts the background color of the card by `75%` prior to the animation starting. Once the animation finishes, the box shadow on the element is set to `rgba(255, 0, 50, 0.4) 0px 4px 16px 6px`, a red glow, and the inline filter is cleared. The animation must be stopped in order to remove the box shadow and play it with the filter again.
366259

367260
See [Methods](#methods) for a complete list of hooks.
368261

369-
<Codepen user="ionic" slug="BaBxmwo" />
262+
import BeforeAndAfterHooks from '@site/static/usage/v7/animations/before-and-after-hooks/index.md';
263+
264+
<BeforeAndAfterHooks />
370265

371266
## Chained Animations
372267

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
```html
2+
<ion-card>
3+
<ion-card-content>Card</ion-card-content>
4+
</ion-card>
5+
6+
<ion-button (click)="play()">Play</ion-button>
7+
<ion-button (click)="pause()">Pause</ion-button>
8+
<ion-button (click)="stop()">Stop</ion-button>
9+
```
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
```ts
2+
import { Component, ElementRef, ViewChildren } from '@angular/core';
3+
import type { QueryList } from '@angular/core';
4+
import type { Animation } from '@ionic/angular';
5+
import { AnimationController, IonCard } from '@ionic/angular';
6+
7+
@Component({
8+
selector: 'app-example',
9+
templateUrl: 'example.component.html',
10+
})
11+
export class ExampleComponent {
12+
@ViewChildren(IonCard, { read: ElementRef }) cardElements: QueryList<ElementRef<HTMLIonCardElement>>;
13+
14+
private animation: Animation;
15+
16+
constructor(private animationCtrl: AnimationController) {}
17+
18+
ngAfterViewInit() {
19+
const card = this.animationCtrl
20+
.create()
21+
.addElement(this.cardElements.get(0).nativeElement)
22+
.duration(2000)
23+
.beforeStyles({
24+
filter: 'invert(75%)',
25+
})
26+
.beforeClearStyles(['box-shadow'])
27+
.afterStyles({
28+
'box-shadow': 'rgba(255, 0, 50, 0.4) 0px 4px 16px 6px',
29+
})
30+
.afterClearStyles(['filter'])
31+
.keyframes([
32+
{ offset: 0, transform: 'scale(1)' },
33+
{ offset: 0.5, transform: 'scale(1.5)' },
34+
{ offset: 1, transform: 'scale(1)' },
35+
]);
36+
37+
this.animation = this.animationCtrl.create().duration(2000).addAnimation([card]);
38+
}
39+
40+
play() {
41+
this.animation.play();
42+
}
43+
44+
pause() {
45+
this.animation.pause();
46+
}
47+
48+
stop() {
49+
this.animation.stop();
50+
}
51+
}
52+
```
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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>Animations</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 { createAnimation } from 'https://cdn.jsdelivr.net/npm/@ionic/core@7/dist/ionic/index.esm.js';
14+
window.createAnimation = createAnimation;
15+
16+
const card = createAnimation()
17+
.addElement(document.querySelector('#card'))
18+
.duration(2000)
19+
.beforeStyles({
20+
filter: 'invert(75%)',
21+
})
22+
.beforeClearStyles(['box-shadow'])
23+
.afterStyles({
24+
'box-shadow': 'rgba(255, 0, 50, 0.4) 0px 4px 16px 6px',
25+
})
26+
.afterClearStyles(['filter'])
27+
.keyframes([
28+
{ offset: 0, transform: 'scale(1)' },
29+
{ offset: 0.5, transform: 'scale(1.5)' },
30+
{ offset: 1, transform: 'scale(1)' },
31+
]);
32+
33+
document.querySelector('#play').addEventListener('click', async () => {
34+
await card.play();
35+
});
36+
37+
document.querySelector('#pause').addEventListener('click', async () => {
38+
await card.pause();
39+
});
40+
41+
document.querySelector('#stop').addEventListener('click', async () => {
42+
await card.stop();
43+
});
44+
</script>
45+
46+
<style>
47+
.container {
48+
flex-direction: column;
49+
}
50+
51+
ion-card {
52+
width: 70%;
53+
}
54+
</style>
55+
</head>
56+
57+
<body>
58+
<ion-app>
59+
<ion-content>
60+
<div class="container">
61+
<ion-card id="card">
62+
<ion-card-content>Card</ion-card-content>
63+
</ion-card>
64+
65+
<div>
66+
<ion-button id="play">Play</ion-button>
67+
<ion-button id="pause">Pause</ion-button>
68+
<ion-button id="stop">Stop</ion-button>
69+
</div>
70+
</div>
71+
</ion-content>
72+
</ion-app>
73+
</body>
74+
</html>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import Playground from '@site/src/components/global/Playground';
2+
3+
import javascript from './javascript.md';
4+
import react from './react.md';
5+
import vue from './vue.md';
6+
7+
import angular_example_component_html from './angular/example_component_html.md';
8+
import angular_example_component_ts from './angular/example_component_ts.md';
9+
10+
<Playground
11+
version="7"
12+
code={{
13+
javascript,
14+
react,
15+
vue,
16+
angular: {
17+
files: {
18+
'src/app/example.component.html': angular_example_component_html,
19+
'src/app/example.component.ts': angular_example_component_ts,
20+
},
21+
},
22+
}}
23+
src="usage/v7/animations/before-and-after-hooks/demo.html"
24+
devicePreview={true}
25+
/>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
```html
2+
<ion-card id="card">
3+
<ion-card-content>Card</ion-card-content>
4+
</ion-card>
5+
6+
<ion-button onclick="animation.play()">Play</ion-button>
7+
<ion-button onclick="animation.pause()">Pause</ion-button>
8+
<ion-button onclick="animation.stop()">Stop</ion-button>
9+
10+
<script>
11+
var animation = createAnimation()
12+
.addElement(document.querySelector('#card'))
13+
.duration(2000)
14+
.beforeStyles({
15+
filter: 'invert(75%)',
16+
})
17+
.beforeClearStyles(['box-shadow'])
18+
.afterStyles({
19+
'box-shadow': 'rgba(255, 0, 50, 0.4) 0px 4px 16px 6px',
20+
})
21+
.afterClearStyles(['filter'])
22+
.keyframes([
23+
{ offset: 0, transform: 'scale(1)' },
24+
{ offset: 0.5, transform: 'scale(1.5)' },
25+
{ offset: 1, transform: 'scale(1)' },
26+
]);
27+
</script>
28+
```
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
```tsx
2+
import React, { useEffect, useRef } from 'react';
3+
import { IonButton, IonCard, IonCardContent, createAnimation } from '@ionic/react';
4+
import type { Animation } from '@ionic/react';
5+
6+
function Example() {
7+
const cardEl = useRef<HTMLIonCardElement | null>(null);
8+
9+
const card = useRef<Animation>();
10+
11+
useEffect(() => {
12+
if (!card.current) {
13+
card.current = createAnimation()
14+
.addElement(cardEl.current!)
15+
.duration(2000)
16+
.beforeStyles({
17+
filter: 'invert(75%)',
18+
})
19+
.beforeClearStyles(['box-shadow'])
20+
.afterStyles({
21+
'box-shadow': 'rgba(255, 0, 50, 0.4) 0px 4px 16px 6px',
22+
})
23+
.afterClearStyles(['filter'])
24+
.keyframes([
25+
{ offset: 0, transform: 'scale(1)' },
26+
{ offset: 0.5, transform: 'scale(1.5)' },
27+
{ offset: 1, transform: 'scale(1)' },
28+
]);
29+
}
30+
}, [cardEl]);
31+
32+
const play = async () => {
33+
await card.current?.play();
34+
};
35+
const pause = () => {
36+
card.current?.pause();
37+
};
38+
const stop = () => {
39+
card.current?.stop();
40+
};
41+
42+
return (
43+
<>
44+
<IonCard ref={cardEl}>
45+
<IonCardContent>Card</IonCardContent>
46+
</IonCard>
47+
48+
<IonButton id="play" onClick={play}>
49+
Play
50+
</IonButton>
51+
<IonButton id="pause" onClick={pause}>
52+
Pause
53+
</IonButton>
54+
<IonButton id="stop" onClick={stop}>
55+
Stop
56+
</IonButton>
57+
</>
58+
);
59+
}
60+
export default Example;
61+
```

0 commit comments

Comments
 (0)