Svelte视图过渡的闪烁

前端开发 2026-07-10

在使用view-transition API时,出现了一些闪烁。我不知道原因是什么。我只是想做一个缩放动画。

我在Svelte REPL有一个演示:https://svelte.dev/playground/d075b2befffb490eaf76f82aba93007d?version=latest

屏幕录制无法捕捉到闪烁,所以我手动录制了。

https://imgur.com/CRDJ6Op // 正常动画

https://imgur.com/mSGqbiB // 2秒动画

这是整段代码:

<script lang="ts">
    let seeking = $state(false);

    function seek() {
        document.startViewTransition(() => {
            seeking = true
        });
    }

    function cancelSeek() {
        document.startViewTransition(() => {
            seeking = false
        });
    }
</script>

<div class="rounded-lg border border-yellow-400/20 min-w-150">
    <div class={['quick-game overflow-hidden', { seeking }]}>
        <div class="relative rounded-lg p-4 [view-transition-name:quick-game-content]">
            {#if seeking}
                <div class="grid items-center gap-4">
                    <p>Seeking game...</p>
                    <p>3+0</p>
                    <p>Blitz</p>
                    <p>Active players: 69420</p>
                    <button class="rounded-lg bg-yellow-600 p-2 py-1 text-black" onclick={cancelSeek}>cancel seek</button>
                </div>
            {:else}
                <div class="grid grid-cols-[repeat(auto-fill,minmax(10rem,1fr))] gap-4">
                    {#each Array.from({ length: 12 }) as _, i}
                        <button
                            class="flex h-full items-center justify-center gap-1 rounded-lg border-2 border-yellow-400 bg-yellow-600/10 p-2 text-xl tracking-wide text-primary transition duration-100 ease-in-out hover:bg-yellow-600/20 hover:text-yellow-400 active:bg-yellow-600/30"
                            onclick={seek}
                        >
                            <div class="flex flex-1 flex-col gap-2 text-start">
                                <p>{i+1}+0</p>
                                <p>Blitz</p>
                            </div>
                            <span>🤓</span>
                        </button>
                    {/each}
                </div>
            {/if}
        </div>
    </div>
</div>

<style>
    ::view-transition-old(quick-game-content) {
        animation: scale-out 2s ease-in-out;
    }
    ::view-transition-new(quick-game-content) {
        animation: scale-in 2s ease-in-out;
    }

    @keyframes scale-in {
        from {
            scale: 0;
            opacity: 0;
        }
        to {
            scale: 1;
            opacity: 1;
        }
    }

    @keyframes scale-out {
        from {
            scale: 1;
            opacity: 1;
        }
        to {
            scale: 0;
            opacity: 0;
        }
    }
</style>

我尝试使用await tick(),但结果仍然一样。

解决方案

也不清楚为什么,也不关心怎么解决。但这个解决了。

::view-transition-group(quick-game-content) {
    animation-duration: 0.35s;
}
::view-transition-old(quick-game-content) {
    animation-name: scale-out;
    animation-timing-function: ease-in-out;
}
::view-transition-new(quick-game-content) {
    animation-name: scale-in;
    animation-timing-function: ease-in-out;
}

出于某种原因,简写形式不管用。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章