Cours Svelte et SvelteKit · Module 9: Transitions et animations
Transitions personnalisées
Dans cette leçon4
Crée tes propres transitions :
Structure d'une transition personnalisée
import { cubicOut } from 'svelte/easing';
function myTransition(node, params) {
return {
delay: params.delay || 0,
duration: params.duration || 400,
easing: params.easing || cubicOut,
css: (t, u) => `
transform: scale(${t});
opacity: ${t};
`
// t : 0 -> 1 (entrée), 1 -> 0 (sortie)
// u : 1 - t
};
}Exemple : Transition de rotation
<script>
import { cubicOut } from 'svelte/easing';
function spin(node, { duration = 500, times = 1 }) {
return {
duration,
css: (t) => {
const degrees = times * 360 * t;
return `
transform: rotate(${degrees}deg) scale(${t});
opacity: ${t};
`;
}
};
}
let visible = $state(true);
</script>
{#if visible}
<div transition:spin={{ duration: 800, times: 2 }}>
Spinning!
</div>
{/if}Transition avec tick (pour l'animation JS)
function typewriter(node, { speed = 50 }) {
const text = node.textContent;
const duration = text.length * speed;
return {
duration,
tick: (t) => {
const i = Math.floor(text.length * t);
node.textContent = text.slice(0, i);
}
};
}draw - Pour SVG
<script>
import { draw } from 'svelte/transition';
let visible = $state(true);
</script>
<svg viewBox="0 0 100 100">
{#if visible}
<path
transition:draw={{ duration: 1000 }}
d="M10 10 L90 10 L90 90 L10 90 Z"
fill="none"
stroke="gold"
stroke-width="2"
/>
{/if}
</svg>Code de cette leçon : App.svelte
<script>
// in: et out: - animations d’entrée/sortie séparées
import { fly, fade, scale } from 'svelte/transition';
let items = $state([
{ id: 1, name: 'Ragnar' },
{ id: 2, name: 'Bjorn' },
{ id: 3, name: 'Ivar' }
]);
let nextId = 4;
function addItem() {
const names = ['Ubbe', 'Sigurd', 'Hvitserk', 'Lagertha', 'Rollo'];
const name = names[Math.floor(Math.random() * names.length)];
items = [...items, { id: nextId++, name }];
}
function removeItem(id) {
items = items.filter(i => i.id !== id);
}
</script>
<main class="in-out-demo">
<h1>in: vs out:</h1>
<p class="subtitle">Animations différentes pour l’entrée et la sortie</p>
<button onclick={addItem}>+ Ajouter un guerrier</button>
<div class="list">
{#each items as item (item.id)}
<div
class="item"
in:fly={{ x: -200, duration: 400 }}
out:fade={{ duration: 200 }}
>
<span>{item.name}</span>
<button onclick={() => removeItem(item.id)}>Retirer</button>
</div>
{/each}
</div>
<section class="code">
<h2>Syntaxe</h2>
<pre>
{"<div"}
in:fly={"{"}{"{"} x: -200 {"}"}{"}"}
out:fade
{">"}
Animations différentes !
{"</div>"}
</pre>
</section>
</main>
<style>
.in-out-demo {
font-family: 'Georgia', serif;
max-width: 400px;
margin: 0 auto;
padding: 2rem;
background: #1a0a0a;
color: #f7d5e8;
min-height: 100vh;
}
h1 {
color: #ff6b6b;
text-align: center;
}
.subtitle {
text-align: center;
color: #a87ca8;
margin-bottom: 1rem;
}
button {
padding: 0.5rem 1rem;
background: #3a1a2a;
color: #f7d5e8;
border: 1px solid #ff6b6b;
border-radius: 4px;
cursor: pointer;
}
.list {
margin-top: 1rem;
}
.item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.75rem;
background: rgba(255, 107, 107, 0.1);
border: 1px solid #ff6b6b;
border-radius: 4px;
margin-bottom: 0.5rem;
}
.item button {
background: #8b0000;
border-color: #8b0000;
padding: 0.25rem 0.5rem;
}
.code {
margin-top: 2rem;
background: rgba(0,0,0,0.5);
border-radius: 8px;
padding: 1rem;
}
.code h2 {
color: #ff6b6b;
font-size: 1rem;
margin-top: 0;
}
.code pre {
font-size: 0.9rem;
margin: 0;
}
</style>Entrées de la documentation utilisées dans cette leçon
Tu as repéré une erreur dans cette leçon ?