Skip to content

Commit 004c78b

Browse files
docs(animation): add playground example for keyframes (#3039)
Co-authored-by: dillionmegida < [email protected]>
1 parent 614519f commit 004c78b

File tree

8 files changed

+266
-84
lines changed

8 files changed

+266
-84
lines changed

docs/utilities/animations.md

Lines changed: 3 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -152,95 +152,14 @@ Ionic Animations allows you to control the intermediate steps in an animation us
152152

153153
Hyphenated CSS properties should be written using camel case when writing keyframes. For example, `border-radius` should be written as `borderRadius`. This also applies to the `fromTo()`, `from(),` and `to()` methods.
154154

155-
### Usage
155+
import Keyframes from '@site/static/usage/v7/animations/keyframes/index.md';
156156

157-
````mdx-code-block
158-
<Tabs
159-
groupId="framework"
160-
defaultValue="javascript"
161-
values={[
162-
{ value: 'javascript', label: 'JavaScript' },
163-
{ value: 'angular', label: 'Angular' },
164-
{ value: 'react', label: 'React' },
165-
{ value: 'vue', label: 'Vue' },
166-
]
167-
}>
168-
<TabItem value="javascript">
157+
<Keyframes />
169158

170-
```javascript
171-
createAnimation()
172-
.addElement(document.querySelector('.square'))
173-
.duration(3000)
174-
.iterations(Infinity)
175-
.keyframes([
176-
{ offset: 0, background: 'red' },
177-
{ offset: 0.72, background: 'var(--background)' },
178-
{ offset: 1, background: 'green' }
179-
]);
180-
```
181-
</TabItem>
182-
<TabItem value="angular">
183-
184-
```javascript
185-
this.animationCtrl.create()
186-
.addElement(this.square.nativeElement)
187-
.duration(3000)
188-
.iterations(Infinity)
189-
.keyframes([
190-
{ offset: 0, background: 'red' },
191-
{ offset: 0.72, background: 'var(--background)' },
192-
{ offset: 1, background: 'green' }
193-
]);
194-
```
195-
</TabItem>
196-
<TabItem value="react">
197-
198-
```tsx
199-
<CreateAnimation
200-
duration={3000}
201-
iterations={Infinity}
202-
keyframes={[
203-
{ offset: 0, background: 'red' },
204-
{ offset: 0.72, background: 'var(--background)' },
205-
{ offset: 1, background: 'green' }
206-
]}
207-
>
208-
...
209-
</CreateAnimation>
210-
```
211-
</TabItem>
212-
<TabItem value="vue">
213-
214-
```javascript
215-
import { createAnimation } from '@ionic/vue';
216-
import { ref } from 'vue';
217-
218-
...
219-
220-
const squareRef = ref();
221-
222-
...
223-
224-
createAnimation()
225-
.addElement(squareRef.value)
226-
.duration(3000)
227-
.iterations(Infinity)
228-
.keyframes([
229-
{ offset: 0, background: 'red' },
230-
{ offset: 0.72, background: 'var(--background)' },
231-
{ offset: 1, background: 'green' }
232-
]);
233-
```
234-
</TabItem>
235-
</Tabs>
236-
````
237-
238-
In the example above, the `.square` element will transition from a red background color, to a background color defined by the `--background` variable, and then transition on to a green background color.
159+
In the example above, the card element will transition from its initial width, to a width defined by the `--width` variable, and then transition on to the final width.
239160

240161
Each keyframe object contains an `offset` property. `offset` is a value between 0 and 1 that defines the keyframe step. Offset values must go in ascending order and cannot repeat.
241162

242-
<Codepen user="ionic" slug="YzKLEzR" />
243-
244163
## Grouped Animations
245164

246165
Multiple elements can be animated at the same time and controlled via a single parent animation object. Child animations inherit properties such as duration, easing, and iterations unless otherwise specified. A parent animation's `onFinish` callback will not be called until all child animations have completed.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
```html
2+
<ion-card #card style="width: 80px; --width: 160px;">
3+
<ion-card-content>Card</ion-card-content>
4+
</ion-card>
5+
<ion-button (click)="play()">Play</ion-button>
6+
<ion-button (click)="pause()">Pause</ion-button>
7+
<ion-button (click)="stop()">Stop</ion-button>
8+
```
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
```ts
2+
import { Component, ElementRef, ViewChild } from '@angular/core';
3+
import type { Animation } from '@ionic/angular';
4+
import { AnimationController, IonCard, IonCardContent } from '@ionic/angular';
5+
6+
@Component({
7+
selector: 'app-example',
8+
templateUrl: 'example.component.html',
9+
})
10+
export class ExampleComponent {
11+
@ViewChild(IonCard, { read: ElementRef }) card: ElementRef<HTMLIonCardElement>;
12+
13+
private animation: Animation;
14+
15+
constructor(private animationCtrl: AnimationController) {}
16+
17+
ngAfterViewInit() {
18+
this.animation = this.animationCtrl
19+
.create()
20+
.addElement(this.card.nativeElement)
21+
.duration(3000)
22+
.iterations(Infinity)
23+
.keyframes([
24+
{ offset: 0, width: '80px' },
25+
{ offset: 0.72, width: 'var(--width)' },
26+
{ offset: 1, width: '240px' },
27+
]);
28+
}
29+
30+
play() {
31+
this.animation.play();
32+
}
33+
34+
pause() {
35+
this.animation.pause();
36+
}
37+
38+
stop() {
39+
this.animation.stop();
40+
}
41+
}
42+
```
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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>Keyframe 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+
<script type="module">
12+
import { createAnimation } from 'https://cdn.jsdelivr.net/npm/@ionic/core@7/dist/ionic/index.esm.js';
13+
14+
const animation = createAnimation()
15+
.addElement(document.querySelector('#card'))
16+
.duration(3000)
17+
.iterations(Infinity)
18+
.keyframes([
19+
{ offset: 0, width: '80px' },
20+
{ offset: 0.72, width: 'var(--width)' },
21+
{ offset: 1, width: '240px' },
22+
]);
23+
24+
document.querySelector('#play').addEventListener('click', () => {
25+
animation.play();
26+
});
27+
28+
document.querySelector('#pause').addEventListener('click', () => {
29+
animation.pause();
30+
});
31+
32+
document.querySelector('#stop').addEventListener('click', () => {
33+
animation.stop();
34+
});
35+
</script>
36+
37+
<style>
38+
.container {
39+
flex-direction: column;
40+
}
41+
42+
ion-card {
43+
width: 80px;
44+
--width: 160px;
45+
}
46+
</style>
47+
</head>
48+
49+
<body>
50+
<div class="container">
51+
<ion-card id="card">
52+
<ion-card-content>Card</ion-card-content>
53+
</ion-card>
54+
<div>
55+
<ion-button id="play">Play</ion-button>
56+
<ion-button id="pause">Pause</ion-button>
57+
<ion-button id="stop">Stop</ion-button>
58+
</div>
59+
</div>
60+
</body>
61+
</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/keyframes/demo.html"
24+
devicePreview={true}
25+
/>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
```html
2+
<ion-card id="card" style="width: 80px; --width: 160px;">
3+
<ion-card-content>Card</ion-card-content>
4+
</ion-card>
5+
<ion-button onclick="animation.play()">Play</ion-button>
6+
<ion-button onclick="animation.pause()">Pause</ion-button>
7+
<ion-button onclick="animation.stop()">Stop</ion-button>
8+
9+
<script>
10+
var animation = createAnimation()
11+
.addElement(document.querySelector('#card'))
12+
.duration(3000)
13+
.iterations(Infinity)
14+
.keyframes([
15+
{ offset: 0, width: '80px' },
16+
{ offset: 0.72, width: 'var(--width)' },
17+
{ offset: 1, width: '240px' },
18+
]);
19+
</script>
20+
```
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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 animation = useRef<Animation | null>(null);
10+
11+
useEffect(() => {
12+
if (animation.current === null) {
13+
animation.current = createAnimation()
14+
.addElement(cardEl.current!)
15+
.duration(3000)
16+
.iterations(Infinity)
17+
.keyframes([
18+
{ offset: 0, width: '80px' },
19+
{ offset: 0.72, width: 'var(--width)' },
20+
{ offset: 1, width: '240px' },
21+
]);
22+
}
23+
}, [cardEl]);
24+
25+
const play = () => {
26+
animation.current?.play();
27+
};
28+
const pause = () => {
29+
animation.current?.pause();
30+
};
31+
const stop = () => {
32+
animation.current?.stop();
33+
};
34+
35+
return (
36+
<>
37+
<IonCard ref={cardEl} style={{ width: '80px', '--width': '160px' } as React.CSSProperties}>
38+
<IonCardContent>Card</IonCardContent>
39+
</IonCard>
40+
<IonButton onClick={play}>Play</IonButton>
41+
<IonButton onClick={pause}>Pause</IonButton>
42+
<IonButton onClick={stop}>Stop</IonButton>
43+
</>
44+
);
45+
}
46+
export default Example;
47+
```
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
```html
2+
<template>
3+
<ion-card ref="cardEl">
4+
<ion-card-content>Card</ion-card-content>
5+
</ion-card>
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+
</template>
10+
11+
<script lang="ts">
12+
import { IonButton, IonCard, IonCardContent, createAnimation } from '@ionic/vue';
13+
import type { Animation } from '@ionic/vue';
14+
15+
import { defineComponent, ref, onMounted } from 'vue';
16+
17+
export default defineComponent({
18+
components: {
19+
IonButton,
20+
IonCard,
21+
IonCardContent,
22+
},
23+
setup() {
24+
const cardEl = ref(null);
25+
26+
let animation: Animation;
27+
28+
onMounted(() => {
29+
animation = createAnimation()
30+
.addElement(cardEl.value.$el)
31+
.duration(3000)
32+
.iterations(Infinity)
33+
.keyframes([
34+
{ offset: 0, width: '80px' },
35+
{ offset: 0.72, width: 'var(--width)' },
36+
{ offset: 1, width: '240px' },
37+
]);
38+
});
39+
40+
const play = () => animation.play();
41+
const pause = () => animation.pause();
42+
const stop = () => animation.stop();
43+
44+
return {
45+
play,
46+
pause,
47+
stop,
48+
cardEl,
49+
};
50+
},
51+
});
52+
</script>
53+
54+
<style>
55+
ion-card {
56+
width: 80px;
57+
--width: 160px;
58+
}
59+
</style>
60+
```

0 commit comments

Comments
 (0)