Reputation: 2506
I'm doing a CSS-based custom animation as shown below, but I do not want to animate on the initial render. At first, I thought I could easily achieve this creating a new flag that gets set on mount. However, I'm not sure how I can achieve this because all variables I create at the top level will cause re-render when it's updated.
I read that anything declared at the top level will cause re-rendering on assignments. So, I'm forced to create this flag inside a function, but doing so doesn't let me access the variable in HTML. How can I achieve this?
<script lang="ts">
import { onMount } from 'svelte';
import classnames from 'classnames';
let element: HTMLDivElement;
let mounted = false;
onMount(() => {
const animationEndHandler = () => {
element.classList.remove(animation);
};
element.addEventListener('animationend', animationEndHandler);
mounted = true; // This needs to not cause re-rendering.
return () => {
element.removeEventListener('animationend', animationEndHandler);
};
});
export let animate: boolean;
export let animation: string;
</script>
<div
class={classnames('animated', { [animation]: animate && mounted })} // <== This attaches the variable `animation` when `animate && mounted` is true.
bind:this={element}
>
<slot />
</div>
Upvotes: 2
Views: 2344
Reputation: 11011
Instead of using class
directive on element, if you add the 'class' in the onMount, should work right? (only thing, we need additionally to add the css animation class name(s) to :global()
scope, as svelte might remove unused css classes).
<script>
onMount(() => {
const animationEndHandler = () => {
element.classList.remove(animation);
};
element.addEventListener('animationend', animationEndHandler);
element.classList.add(animation);
return () => {
element.removeEventListener('animationend', animationEndHandler);
};
});
</script>
Upvotes: 0
Reputation: 2506
I solved it by creating an integer counter and validate that it's greater than 0. This is ugly, but I can't find any other ways.
Upvotes: 1