如何在SvelteKit中实现Hero动画?求示例或自研方案
SvelteKit 跨页 Hero 动画实现方案
原生支持现状
SvelteKit 目前没有内置类似 Flutter 的 Hero 组件匹配机制,官方文档和主流生态包中也没有开箱即用的实现方案。
自研简易实现步骤
核心逻辑是通过状态传递捕获元素初始状态 + Svelte 动画系统驱动过渡,模拟跨页组件的衔接动画:
1. 列表页捕获元素信息并传递
点击目标图片时,获取它的位置、尺寸、资源地址等信息,通过路由跳转的 state 参数传递到详情页:
<!-- 图库列表页组件 --> <script> import { goto } from '$app/navigation'; function handleImageClick(img) { const rect = img.getBoundingClientRect(); goto('/image-detail', { state: { hero: { src: img.src, x: rect.left, y: rect.top, w: rect.width, h: rect.height } } }); } </script> <img src="/gallery/photo-1.jpg" on:click={(e) => handleImageClick(e.target)} alt="gallery photo" />
2. 详情页创建过渡占位元素
在详情页取出路由传递的状态,生成和列表页图片完全重合的占位元素,通过 Svelte 的过渡动画让它平滑过渡到详情页图片的最终位置:
<!-- 图片详情页组件 --> <script> import { page } from '$app/stores'; import { fly } from 'svelte/transition'; import { cubicOut } from 'svelte/easing'; let heroData = $page.state.hero; let finalRect; let showPlaceholder = true; function getFinalPosition(img) { finalRect = img.getBoundingClientRect(); // 确保DOM渲染完成后启动动画 requestAnimationFrame(() => { showPlaceholder = false; }); } </script> <!-- 过渡占位层 --> {#if heroData && showPlaceholder} <div class="hero-placeholder" style={` position: fixed; z-index: 9999; top: ${heroData.y}px; left: ${heroData.x}px; width: ${heroData.w}px; height: ${heroData.h}px; background: url(${heroData.src}) center/cover no-repeat; `} in:fly={{ duration: 350, easing: cubicOut, x: finalRect?.left - heroData.x || 0, y: finalRect?.top - heroData.y || 0, width: finalRect?.width || heroData.w, height: finalRect?.height || heroData.h }} /> {/if} <!-- 详情页目标图片 --> <img src={heroData?.src} alt="detail photo" class="detail-image" on:load={(e) => getFinalPosition(e.target)} style="opacity: {showPlaceholder ? 0 : 1};" /> <style> .detail-image { transition: opacity 350ms cubic-bezier(0.25, 1, 0.5, 1); width: 100%; max-width: 800px; margin: 0 auto; } </style>
3. 回退动画优化
从详情页返回列表页时,可反向执行上述逻辑:捕获详情页图片的当前位置,传递回列表页,创建占位元素过渡回原图片位置。
社区参考示例
社区有非官方的 Demo 仓库基于上述思路实现了完整的 Hero 动画,核心逻辑均复用 Svelte 原生动画系统,可直接适配 SvelteKit 路由场景。
内容的提问来源于stack exchange,提问作者yoyo
相关产品推荐
相关产品推荐

