【小沐学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???
如果您需要相关功能的代码定制化开发,可以留言私信作者;(✿◡‿◡)
感谢各位童鞋们的支持!( ´ ▽´ )ノ ( ´ ▽´)っ!!!

相关推荐
DC...21 分钟前
vue滑块组件设计与实现
前端·javascript·vue.js
H5开发新纪元39 分钟前
Vite 项目打包分析完整指南:从配置到优化
前端·vue.js
吃面必吃蒜2 小时前
从 Vue 到 React:React 合成事件
javascript·vue.js·react.js
前端练习生2 小时前
vue2如何二次封装表单控件如input, select等
前端·javascript·vue.js
举个栗子dhy2 小时前
【血缘关系图下钻节点,节点展开收起功能,递归和迭代问题处理】
javascript·react.js
三年三月2 小时前
three中相机
three.js
不爱说话郭德纲2 小时前
Vue scoped都用过吧,它是怎么实现样式隔离的?React又是怎么实现的
前端·javascript·vue.js
OpenTiny社区2 小时前
直播预告|TinyVue 组件库高级用法:定制你的企业级UI体系
前端·vue.js·开源
我怎么能这么帅气2 小时前
picocolors:终端输出美化的极简利器,快如闪电的ANSIColor库!
javascript·npm