首页 > 解决方案 > 是否可以手动取消和重新触发 Svelte 动画?

问题描述

我有一个动画,它取决于可写存储的值。

例如:

{#if $isWorking}
    <span in:fade="{{duration: 200, delay: 750}}">Working...</span>
{/if}

问题是如果 store 的值变化得足够快,则转换不会重新开始。这是一个演示此行为的 REPL。

我想这是因为 Svelte 非常高效。我的猜测是,如果在$isWorking下一帧开始时 的值相同,Svelte 将确定它没有更改并继续进行转换。

这似乎是一个很好的默认行为,但有没有办法避免这种情况并手动重置动画?$isWorking在这种情况下,每当商店更改时重新启动延迟?

我想出了一个技巧来避免使用delay转换的属性并使用以下方法实现它setTimeout

let show = false;
let timeout;

isWorking.subscribe((value) => {
    show = false;
    if (timeout) clearTimeout(timeout);

    timeout = setTimeout(() => {
        showState = true;
    }, 750);
});

{#if show}
    <span in:fade="{{duration: 200}}">Working</span>
{/if}

有没有更优雅的方法来解决这个问题?

标签: javascriptsvelte

解决方案


你可以用tick这个。

<script>
    import { fade } from 'svelte/transition';
    import { tick } from 'svelte';
    let show = false;
    
    async function onInput () {
        show = false;
        await tick();
        show = true;
    }
</script>

<input on:input={onInput}>

{#if show}
    <span in:fade="{{duration: 200, delay: 500}}">working...</span>
{/if}

Svelte 收集所有的 intro 和 outros 并等到下一帧以批量更新视图。如果您的状态在同一个微任务中发生变化,那么 Svelte 不会注意到它。在这种情况下,您可以使用tick强制 Svelte 更新视图。


推荐阅读