返回 slidev
animations.md
根目录 / docs / guide / animations.md
1 ---
2 outline: deep
3 ---
4
5 # Animation
6
7 Animation is an essential part of slide presentations. Slidev provides a variety of ways to animate your slides, from the simple to the complex. This guide will show you how to use them effectively.
8
9 ## Click Animation {#click-animation}
10
11 A "**click**" can be considered as the unit of animation steps in slides. A slide can have one or more clicks, and each click can trigger one or more animations - for example, revealing or hiding elements.
12
13 > [!NOTE]
14 > Since v0.48.0, we've rewritten the click animations system with much more consistent behaviors. It might change the behaviors of your existing slides in edge cases. While this page is showing the new click system, you can find more details about the refactor in [#1279](https://github.com/slidevjs/slidev/pull/1279).
15
16 ### `v-click` {#v-click}
17
18 To apply show/hide "click animations" for elements, you can use the `<v-click>` component or the `v-click` directive.
19
20 <!-- eslint-skip -->
21
22 ```md
23 <!-- Component usage:
24 this will be invisible until you press "next" -->
25 <v-click> Hello World! </v-click>
26
27 <!-- Directive usage:
28 this will be invisible until you press "next" the second time -->
29 <div v-click class="text-xl"> Hey! </div>
30 ```
31
32 ### `v-after` {#v-after}
33
34 `v-after` will turn the element visible when the previous `v-click` is triggered.
35
36 ```md
37 <div v-click> Hello </div>
38 <div v-after> World </div> <!-- or <v-after> World </v-after> -->
39 ```
40
41 When you press "next", both `Hello` and `World` will show up together.
42
43 ### Hide after clicking {#hide-after-clicking}
44
45 Add a `.hide` modifier to `v-click` or `v-after` directives to make elements invisible after clicking, instead of showing up.
46
47 ```md
48 <div v-click> Visible after 1 click </div>
49 <div v-click.hide> Hidden after 2 clicks </div>
50 <div v-after.hide> Hidden after 2 clicks </div>
51 ```
52
53 For the components, you can use the `hide` prop to achieve the same effect:
54
55 ```md
56 <v-click> Visible after 1 click </v-click>
57 <v-click hide> Hidden after 2 clicks </v-click>
58 <v-after hide> Also hidden after 2 clicks </v-after>
59 ```
60
61 ### `v-clicks` {#v-clicks}
62
63 `v-clicks` is only provided as a component. It's a shorthand to apply the `v-click` directive to all its child elements. It is especially useful when working with lists and tables.
64
65 ```md
66 <v-clicks>
67
68 - Item 1
69 - Item 2
70 - Item 3
71
72 </v-clicks>
73 ```
74
75 An item will become visible each time you click "next".
76 It accepts a `depth` prop for nested list:
77
78 ```md
79 <v-clicks depth="2">
80
81 - Item 1
82 - Item 1.1
83 - Item 1.2
84 - Item 2
85 - Item 2.1
86 - Item 2.2
87
88 </v-clicks>
89 ```
90
91 Also, you can use the `every` prop to specify the number of items to show after each click:
92
93 ```md
94 <v-clicks every="2">
95
96 - Item 1.1
97 - Item 1.2
98 - Item 2.1
99 - Item 2.2
100
101 </v-clicks>
102 ```
103
104 ### Positioning {#positioning}
105
106 By default, the clicking animations are triggered one by one. You can customize the animation "position" of elements by using the `at` prop or the `v-click` directive with value.
107
108 Like the CSS layout system, click-animated elements can be "relative" or "absolute":
109
110 #### Relative Position {#relative-position}
111
112 This actual position of relative elements is calculated based on the previous relative elements:
113
114 ````md
115 <div v-click> visible after 1 click </div>
116 <v-click at="+2"><div> visible after 3 clicks </div></v-click>
117 <div v-click.hide="'-1'"> hidden after 2 clicks </div>
118
119 ```js {none|1|2}{at:'+5'}
120 1 // highlighted after 7 clicks
121 2 // highlighted after 8 clicks
122 ```
123 ````
124
125 > [!NOTE]
126 > The default value of `v-click` is `'+1'` when you don't specify it.
127
128 In fact, `v-after` are just shortcuts for `v-click` with `at` prop:
129
130 ```md
131 <!-- The following 2 usages are equivalent -->
132 <img v-after />
133 <img v-click="'+0'" />
134
135 <!-- The following 3 usages are equivalent -->
136 <img v-click />
137 <img v-click="'+1'" />
138 <v-click-gap size="1" /><img v-after />
139 ```
140
141 ::: tip `at` prop value format
142 Only string values starting with `'+'` or `'-'` like `'+1'` are treated as relative positions:
143
144 | Value | Kind |
145 | -------------- | -------- |
146 | `'-1'`, `'+1'` | Relative |
147 | `+1` === `1` | Absolute |
148 | `'1'` | Absolute |
149
150 So don't forget the single quotes for the relative values.
151 :::
152
153 #### Absolute Position {#absolute-position}
154
155 The given value is the exact click count to trigger this animation:
156
157 ````md
158 <div v-click="3"> visible after 3 clicks </div>
159 <v-click at="2"><div> visible after 2 clicks </div></v-click>
160 <div v-click.hide="1"> hidden after 1 click </div>
161
162 ```js {none|1|2}{at:3}
163 1 // highlighted after 3 clicks
164 2 // highlighted after 4 clicks
165 ```
166 ````
167
168 #### Mixed Case {#mixed-case}
169
170 You can mix the absolute and relative positions:
171
172 ```md
173 <div v-click> visible after 1 click </div>
174 <div v-click="3"> visible after 3 clicks </div>
175 <div v-click> visible after 2 click </div>
176 <div v-click="'-1'"> visible after 1 click </div>
177 <div v-click="4"> visible after 4 clicks </div>
178 ```
179
180 The following example synchronizes the highlighting of the two code blocks:
181
182 ````md {1,6}
183 ```js {1|2}{at:1}
184 1 + 1
185 'a' + 'b'
186 ```
187
188 ```js {1|2}{at:1}
189 = 2
190 = 'ab'
191 ```
192 ````
193
194 ### Enter & Leave {#enter-leave}
195
196 You can also specify the enter and leave index for the `v-click` directive by passing an array. The end index is exclusive.
197
198 ```md
199 <div v-click.hide="[2, 4]">
200 This will be hidden at click 2 and 3 (and shown otherwise).
201 </div>
202 <div v-click />
203 <div v-click="['+1', '+1']">
204 This will be shown only at click 2 (and hidden otherwise).
205 </div>
206 ```
207
208 You can also use `v-switch` to achieve the same effect:
209
210 ```md
211 <v-switch>
212 <template #1> show at click 1, hide at click 2. </template>
213 <template #2> show at click 2, hide at click 5. </template>
214 <template #5-7> show at click 5, hide at click 7. </template>
215 </v-switch>
216 ```
217
218 See [`VSwitch` Component](/builtin/components#vswitch) for more details.
219
220 ### Custom Total Clicks Count {#total}
221
222 By default, Slidev automatically calculates how many clicks are required before going to the next slide. You can override this via the `clicks` frontmatter option:
223
224 ```yaml
225 ---
226 # 10 clicks in this slide, before going to the next slide
227 clicks: 10
228 ---
229 ```
230
231 ### Click Animation Presets {#click-animation-presets}
232
233 You can define default click animation presets in headmatter/frontmatter:
234
235 ```yaml
236 ---
237 clickAnimation: up
238 ---
239 ```
240
241 Or specify them per element with directive modifiers:
242
243 ```md
244 <div v-click>Uses default animation preset defined in frontmatter</div>
245 <div v-click.scale>Scales up when showing and scales down when hiding</div>
246 <div v-click.fade.right>Composes multiple animations: fade and right</div>
247 <div v-click.none>No animation for this element</div>
248 ```
249
250 There are some built-in presets available for you to use:
251
252 - `fade`: Fade in from opacity 0.5 to 1
253 - `fade-in`: Fade in from opacity 0 to 1
254 - `up`: Translate 20px up
255 - `down`: Translate 20px down
256 - `left`: Translate 20px left
257 - `right`: Translate 20px right
258 - `scale`: Scale to 0.9
259 - `none`: Disables animation for this element
260
261 And you can also define your own presets with custom CSS rules for `.slidev-vclick-anim-{presetName}`:
262
263 ```css
264 .slidev-vclick-anim-pop.slidev-vclick-hidden {
265 transform: scale(0.96) translateY(8px);
266 }
267 ```
268
269 ### Element Transitions {#element-transitions}
270
271 When you apply the `v-click` directive to your elements, it will attach the class name `slidev-vclick-target` to it. When the elements are hidden, the class name `slidev-vclick-hidden` will also be attached. For example:
272
273 ```html
274 <div class="slidev-vclick-target slidev-vclick-hidden">Text</div>
275 ```
276
277 After a click, it may become:
278
279 ```html
280 <div class="slidev-vclick-target">Text</div>
281 ```
282
283 By default, a subtle opacity transition is applied to those classes:
284
285 ```css
286 /* below shows the default style */
287
288 .slidev-vclick-target {
289 transition: opacity 100ms ease;
290 }
291
292 .slidev-vclick-hidden {
293 opacity: 0;
294 pointer-events: none;
295 }
296 ```
297
298 You can override them to customize the transition effects in your custom stylesheets. For example, you can achieve the scaling up transitions by:
299
300 ```css
301 /* styles.css */
302
303 .slidev-vclick-target {
304 transition: all 500ms ease;
305 }
306
307 .slidev-vclick-hidden {
308 transform: scale(0);
309 }
310 ```
311
312 To specify animations for only certain slides or layouts:
313
314 ```scss
315 .slidev-page-7,
316 .slidev-layout.my-custom-layout {
317 .slidev-vclick-target {
318 transition: all 500ms ease;
319 }
320
321 .slidev-vclick-hidden {
322 transform: scale(0);
323 }
324 }
325 ```
326
327 Learn more about [customizing styles](/custom/directory-structure#style).
328
329 ## Motion {#motion}
330
331 Slidev has [@vueuse/motion](https://motion.vueuse.org/) built-in. You can use the `v-motion` directive to any elements to apply motion to them. For example
332
333 ```html
334 <div
335 v-motion
336 :initial="{ x: -80 }"
337 :enter="{ x: 0 }"
338 :leave="{ x: 80 }"
339 >
340 Slidev
341 </div>
342 ```
343
344 The text `Slidev` will move from `-80px` to its original position when entering the slide. When leaving, it will move to `80px`.
345
346 > Before v0.48.9, you need to add `preload: false` to the slide's frontmatter to enable motion.
347
348 ### Motion with Clicks {#motion-with-clicks}
349
350 > Available since v0.48.9
351
352 You can also trigger the motion by clicks:
353
354 ```html
355 <div
356 v-motion
357 :initial="{ x: -80 }"
358 :enter="{ x: 0, y: 0 }"
359 :click-1="{ x: 0, y: 30 }"
360 :click-2="{ y: 60 }"
361 :click-2-4="{ x: 40 }"
362 :leave="{ y: 0, x: 80 }"
363 >
364 Slidev
365 </div>
366 ```
367
368 Or combine `v-click` with `v-motion`:
369
370 ```html
371 <div v-click="[2, 4]" v-motion
372 :initial="{ x: -50 }"
373 :enter="{ x: 0 }"
374 :leave="{ x: 50 }"
375 >
376 Shown at click 2 and hidden at click 4.
377 </div>
378 ```
379
380 The meanings of variants:
381
382 - `initial`: When `currentPage < thisPage`, or `v-click` hides the current element because `$clicks` is too small.
383 - `enter`: When `currentPage === thisPage`, and `v-click` shows the element. _Priority: lowest_
384 - `click-x`: `x` is a number representing the **absolute** click num. The variant will take effect if `$clicks >= x`. _Priority: `x`_
385 - `click-x-y`: The variant will take effect if `x <= $clicks < y`. _Priority: `x`_
386 - `leave`: `currentPage > thisPage`, or `v-click` hides the current element because `$clicks` is too large.
387
388 The variants will be combined according to the priority defined above.
389
390 ::: warning
391 Due to a Vue internal [bug](https://github.com/vuejs/core/issues/10295), currently **only** `v-click` applied to the same element as `v-motion` can control the motion animation. As a workaround, you can use something like `v-if="3 < $clicks"` to achieve the same effect.
392 :::
393
394 Learn more: [Demo](https://sli.dev/demo/starter/10) | [@vueuse/motion](https://motion.vueuse.org/) | [v-motion](https://motion.vueuse.org/features/directive-usage) | [Presets](https://motion.vueuse.org/features/presets)
395
396 ## Slide Transitions {#slide-transitions}
397
398 <div id="pages-transitions" />
399
400 Slidev supports slide transitions out of the box. You can enable it by setting the `transition` frontmatter option:
401
402 ```md
403 ---
404 transition: slide-left
405 ---
406 ```
407
408 This will give you a nice sliding effects on slide switching. Setting it in the headmatter will apply this to all slides. You can also set different transitions per slide in frontmatters.
409
410 ### Builtin Transitions {#builtin-transitions}
411
412 - `fade` - Crossfade in/out
413 - `fade-out` - Fade out and then fade in
414 - `slide-left` - Slides to the left (slide to right when going backward)
415 - `slide-right` - Slides to the right (slide to left when going backward)
416 - `slide-up` - Slides to the top (slide to bottom when going backward)
417 - `slide-down` - Slides to the bottom (slide to top when going backward)
418 - `view-transition` - Via the view transitions API
419
420 ### View Transition API {#view-transitions}
421
422 The View Transitions API provides a mechanism for easily creating animated transitions between different DOM states. Learn more about it in [View Transitions API - MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API).
423
424 :::warning
425 Experimental: This is not supported by all browsers. Check the [Browser compatibility table](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API#browser_compatibility) carefully before using this.
426 :::
427
428 You can use the `view-transition-name` CSS property to name view transitions, which creates connections between different page elements and smooth transitions when switching slides.
429
430 You can enable [Comark Syntax](/guide/syntax#comark-syntax) support to conveniently name view-transitions:
431
432 ```md
433 ---
434 transition: view-transition
435 comark: true
436 ---
437
438 # View Transition {.inline-block.view-transition-title}
439
440 ---
441
442 # View Transition {.inline-block.view-transition-title}
443 ```
444
445 ### Custom Transitions {#custom-transitions}
446
447 Slidev's slide transitions are powered by [Vue Transition](https://vuejs.org/guide/built-ins/transition.html). You can provide your custom transitions by:
448
449 ```md
450 ---
451 transition: my-transition
452 ---
453 ```
454
455 and then in your custom stylesheets:
456
457 ```css
458 .my-transition-enter-active,
459 .my-transition-leave-active {
460 transition: opacity 0.5s ease;
461 }
462
463 .my-transition-enter-from,
464 .my-transition-leave-to {
465 opacity: 0;
466 }
467 ```
468
469 Learn more about how it works in [Vue Transition](https://vuejs.org/guide/built-ins/transition.html).
470
471 ### Forward & Backward Transitions {#forward-backward-transitions}
472
473 You can specify different transitions for forward and backward navigation using `|` as a separator in the transition name:
474
475 ```md
476 ---
477 transition: go-forward | go-backward
478 ---
479 ```
480
481 With this, when you go from slide 1 to slide 2, the `go-forward` transition will be applied. When you go from slide 2 to slide 1, the `go-backward` transition will be applied.
482
483 ### Advanced Usage {#advanced-usage}
484
485 The `transition` field accepts an option that will passed to the [`<TransitionGroup>`](https://vuejs.org/api/built-in-components.html#transition) component. For example:
486
487 ```md
488 ---
489 transition:
490 name: my-transition
491 enterFromClass: custom-enter-from
492 enterActiveClass: custom-enter-active
493 ---
494 ```
495
495 lines MARKDOWN