【小沐学Web3D】three.js 加载三维模型(Svelte.js)

文章目录

  • 1、简介
    • [1.1 Three.js](#1.1 Three.js)
    • [1.2 Svelte.js](#1.2 Svelte.js)
  • 2、测试
    • [2.1 初始化环境](#2.1 初始化环境)
    • [2.2 直接主页面展示](#2.2 直接主页面展示)
    • [2.3 创建子页面展示](#2.3 创建子页面展示)
  • 结语

1、简介

1.1 Three.js

Three.js 是一个功能强大的 3D 图形库,用于在网页上创建和显示交互式 3D 图形。它基于 WebGL,提供了简单易用的 API,帮助开发者快速构建复杂的 3D 场景。

bash 复制代码
npm install three

1.2 Svelte.js

https://svelte.dev/

Svelte 是一个用于构建 Web 应用的工具。像其他用户界面框架一样,它允许你以声明式的方式使用组件构建应用,这些组件结合了标记、样式和行为。

bash 复制代码
npx sv create myapp
cd myapp
npm install
npm run dev
# or
npm run dev -- --open

Svelte 是一种新兴的前端 JavaScript 框架,它通过编译时优化来提供高性能的用户界面。与其它框架不同的是,Svelte 在构建阶段而非运行时执行大部分优化工作,这意味着最终生成的应用程序体积更小、性能更好。

2、测试

2.1 初始化环境

Svelte 依赖于 Node.js 和 npm 进行包管理和编译,可通过在终端或命令提示符中运行node -v和npm -v命令来检查是否已安装。

bash 复制代码
node -v
npm -v

ite 是一个快速的前端构建工具,能为 Svelte 项目提供便捷的开发体验。在终端或命令提示符中执行命令npm create vite@latest my-svelte-app,其中my-svelte-app是项目名称,可根据自己的需求修改。

bash 复制代码
npm create vite@latest my-svelte-app

执行命令后,会提示选择框架,使用方向键选中 Svelte 选项后回车;

接着再选择 JavaScript 或 TypeScript,一般初学者可先选择 JavaScript。

然后进入项目目录cd my-svelte-app,再运行npm install命令安装项目所需的依赖。

bash 复制代码
cd my-svelte-app
npm install
npm run dev
# or
npm run dev -- --open 

安装完依赖后,使用npm run dev命令启动开发服务器,服务器启动后会在终端输出一个本地服务器地址,通常是http://localhost:5173,打开浏览器访问该地址,即可看到默认的 Svelte 项目页面。

2.2 直接主页面展示

  • App.svelte:
html 复制代码
<script>
  import { onMount} from 'svelte';
  import * as THREE from 'three';

  let container;
  let scene, camera, renderer;
  let cube;

  // 初始化场景
  function init() {
    if (!container) return; // 如果 container 未挂载,则返回

    // 创建场景
    scene = new THREE.Scene();
    scene.background = new THREE.Color(0x000000);

    // 创建相机
    camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);
    camera.position.z = 5;

    // 创建渲染器
    renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(container.clientWidth, container.clientHeight);
    renderer.setPixelRatio(window.devicePixelRatio);
    container.appendChild(renderer.domElement); // 将渲染器的 container 添加到 div 中

    // 创建立方体
    const geometry = new THREE.BoxGeometry();
    const material = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: false });
    cube = new THREE.Mesh(geometry, material);
    scene.add(cube);

    // 添加光源
    const ambientLight = new THREE.AmbientLight(0x404040); // 环境光
    scene.add(ambientLight);

    const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); // 平行光
    directionalLight.position.set(1, 1, 1);
    scene.add(directionalLight);

    // 开始动画
    animate();
  }

  // 动画函数
  function animate() {
    requestAnimationFrame(animate);
    
    // 旋转立方体
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;

    renderer.render(scene, camera);
  }

  // 处理窗口大小变化
  function onWindowResize() {
    if (!container) return; // 如果 container 未挂载,则返回
    if (!camera || !renderer) return; // 如果相机或渲染器未初始化,则返回

    camera.aspect = container.clientWidth / container.clientHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(container.clientWidth, container.clientHeight);
  }

  // 监听窗口大小变化
  window.addEventListener('resize', onWindowResize);

  // 当组件挂载到DOM时初始化
  onMount(() => {
    init();
  });

</script>

<div bind:this={container} style="width: 100%; height: 100vh;"></div>

再次刷新http://localhost:5173

修改app.css如下:

html 复制代码
:root {
  font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
  line-height: 1.5;
  font-weight: 400;

  color-scheme: light dark;
  color: rgba(255, 255, 255, 0.87);
  background-color: #242424;

  font-synthesis: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  margin: 0;
  min-width: 320px;
}

#app {
  margin: 0 auto;
  text-align: center;
}

再次刷新http://localhost:5173

欧克!!!

2.3 创建子页面展示

  • App.svelte:
html 复制代码
<script>
  import Cube from './Cube.svelte';
</script>

<main>
  <h1>Three.js 立方体示例</h1>
  <Cube />
</main>

<style>
  main {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100vh;
    background-color: #f0f0f0;
  }

  h1 {
    margin-bottom: 20px;
  }
</style>
  • Cube.svelte:
html 复制代码
<script>
    import * as THREE from 'three';
    import { onMount } from 'svelte';

    let container;

    onMount(() => {
        if (!container) {
            console.error('Container not found!');
            return;
        }

        try {
            const scene = new THREE.Scene();
            const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);
            camera.position.z = 5;

            const renderer = new THREE.WebGLRenderer({ antialias: true });
            renderer.setSize(container.clientWidth, container.clientHeight);
            container.appendChild(renderer.domElement);

            const geometry = new THREE.BoxGeometry();
            const material = new THREE.MeshBasicMaterial({ color: 0x00ffff });
            const cube = new THREE.Mesh(geometry, material);
            scene.add(cube);

            const ambientLight = new THREE.AmbientLight(0x404040);
            scene.add(ambientLight);
            const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
            directionalLight.position.set(0, 1, 0);
            scene.add(directionalLight);

            function animate() {
                requestAnimationFrame(animate);
                cube.rotation.x += 0.01;
                cube.rotation.y += 0.01;
                renderer.render(scene, camera);
            }
            animate();

            window.addEventListener('resize', () => {
                camera.aspect = container.clientWidth / container.clientHeight;
                camera.updateProjectionMatrix();
                renderer.setSize(container.clientWidth, container.clientHeight);
            });

        } catch (error) {
            console.error('Error initializing Three.js:', error);
        }
    });
</script>

<div bind:this={container} style="width: 100%; height: 100vh;"></div>

运行,在浏览器查看如下:

结语

如果您觉得该方法或代码有一点点用处,可以给作者点个赞,或打赏杯咖啡;╮( ̄▽ ̄)╭
如果您感觉方法或代码不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进;o_O???
如果您需要相关功能的代码定制化开发,可以留言私信作者;(✿◡‿◡)
感谢各位童鞋们的支持!( ´ ▽´ )ノ ( ´ ▽´)っ!!!

相关推荐
伍哥的传说6 小时前
CSS+JavaScript 禁用浏览器复制功能的几种方法
前端·javascript·css·vue.js·vue·css3·禁用浏览器复制
lichenyang4536 小时前
Axios封装以及添加拦截器
前端·javascript·react.js·typescript
苹果醋36 小时前
iview中实现点击表格单元格完成编辑和查看(span和input切换)
运维·vue.js·spring boot·nginx·课程设计
武昌库里写JAVA6 小时前
iView Table组件二次封装
vue.js·spring boot·毕业设计·layui·课程设计
Trust yourself2436 小时前
在easyui中如何设置自带的弹窗,有输入框
前端·javascript·easyui
烛阴6 小时前
Tile Pattern
前端·webgl
前端工作日常7 小时前
前端基建的幸存者偏差
前端·vue.js·前端框架
Feather_748 小时前
从Taro的Dialog.open出发,学习远程控制组件之【事件驱动】
javascript·学习·taro
\光辉岁月/8 小时前
Axios基本使用
javascript·axios
波波鱼દ ᵕ̈ ૩9 小时前
学习:JS[6]环境对象+回调函数+事件流+事件委托+其他事件+元素尺寸位置
前端·javascript·学习