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

Svelte中先加载全局加载器再异步加载Three.js大动画组件的方案

优化实现思路(Svelte + Three.js 全屏预加载器)

1. 优先渲染加载器,避免初始阻塞

直接在根组件(如App.svelte)最外层编写加载器DOM,默认显示,让浏览器优先渲染加载器,无需等待任何JS打包块或资源加载完成。加载器的CSS建议内联或放在全局样式最顶部,避免出现无样式闪烁(FOUC)。

<script>
  let loaded = false;
  let loadError = false;

  import { onMount } from 'svelte';
  import { fade } from 'svelte/transition';
</script>

<!-- 优先渲染的全屏加载器 -->
{#if !loaded && !loadError}
  <div class="loader-overlay" transition:fade={{ duration: 300 }}>
    <div class="loader-spinner"></div>
    <p>加载资源中...</p>
  </div>
{:else if loadError}
  <div class="error-state">加载失败,请刷新页面重试</div>
{:else}
  <!-- Three.js动画组件,加载完成后才渲染 -->
  <ThreeScene />
{/if}

<style>
  .loader-overlay {
    position: fixed;
    inset: 0;
    background: #1a1a1a;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    z-index: 9999;
    color: #fff;
  }

  .loader-spinner {
    width: 60px;
    height: 60px;
    border: 4px solid #333;
    border-top-color: #0070f3;
    border-radius: 50%;
    animation: spin 1s linear infinite;
  }

  @keyframes spin {
    to { transform: rotate(360deg); }
  }
</style>

2. 懒加载Three.js及依赖,分离打包块

不要在根组件顶部同步导入Three.js核心或大型动画组件,改用**动态import()**异步加载,将非初始必需的代码拆分到独立打包块,减小初始加载体积,让加载器更快显示。

<script>
  // ... 其他变量定义
  
  onMount(async () => {
    try {
      // 异步加载Three.js核心(可指定子模块减小体积,如仅加载需要的Loader)
      await import('three/addons/loaders/GLTFLoader.js');
      // 异步加载自定义动画组件
      const { default: ThreeScene } = await import('./components/ThreeScene.svelte');
      // 批量加载资源(模型、纹理、 shader 等)
      await Promise.all([
        loadGLTFModel('/models/animation.glb'),
        loadTexture('/textures/envmap.hdr')
      ]);
      
      loaded = true;
    } catch (err) {
      loadError = true;
      console.error('资源加载失败:', err);
    }
  });

  // 封装资源加载函数
  async function loadGLTFModel(url) {
    const { GLTFLoader } = await import('three/addons/loaders/GLTFLoader.js');
    return new Promise((resolve, reject) => {
      new GLTFLoader().load(url, resolve, null, reject);
    });
  }
</script>

3. 添加加载进度反馈

使用Three.js的LoadingManager统一管理所有资源加载,实时更新进度值,给用户明确的加载状态,避免等待焦虑。

<script>
  import { LoadingManager } from 'three';
  let progress = 0;

  onMount(async () => {
    const manager = new LoadingManager();
    // 实时更新加载进度
    manager.onProgress = (_url, loadedItems, totalItems) => {
      progress = Math.round((loadedItems / totalItems) * 100);
    };
    manager.onLoad = () => loaded = true;

    // 绑定manager到所有资源加载器
    const gltfLoader = new GLTFLoader(manager);
    await gltfLoader.loadAsync('/models/animation.glb');
    // 其他资源加载...
  });
</script>

{#if !loaded}
  <div class="loader-overlay">
    <div class="progress-bar">
      <div class="progress-fill" style="width: {progress}%"></div>
    </div>
    <p>{progress}% 加载中...</p>
  </div>
{/if}

4. 预加载关键资源加速加载

在index.html的<head>中添加<link rel="preload">,让浏览器优先加载Three.js打包块、核心模型/纹理等关键资源,缩短总加载时间。

<head>
  <!-- 预加载Three.js组件打包块 -->
  <link rel="preload" href="/build/three-scene.js" as="script">
  <!-- 预加载核心3D模型 -->
  <link rel="preload" href="/models/animation.glb" as="fetch" crossorigin>
</head>

内容的提问来源于stack exchange,提问作者Noir

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 06:22:46