You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 05:37:24