three.js 最小环境搭建

news2024/12/27 13:02:10

完整目录:
在这里插入图片描述

1、html

<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <style>
      html,
      body {
        width: 100%;
        height: 100%;
        overflow: hidden;
        margin: 0;
        padding: 0;
      }

      #app {
        width: 100%;
        height: 100%;
      }

    </style>


    <script type="importmap">
    {
      "imports": {
        "three": "./three/three.module.js",
        "three/examples/": "./three/examples/"
      }
    }
  </script>

    <script type="module">
      import * as THREE from 'three'
      import { Stage } from './Stage.js'
      window.THREE = THREE;

      class HelloWorldDemo {
        constructor(stage) {
          this.stage = stage;
          this.addBox(100);
        }

        addBox(size) {
          var geometry = new THREE.BoxGeometry(size, size, size);
          var material = new THREE.MeshBasicMaterial({
            color: 0x63e42a,
            emissive: 0x072534,
            side: THREE.DoubleSide,
          })
          var cube = new THREE.Mesh(geometry, material);
          cube.name = "test_cube"
          this.stage.scene.add(cube);
          return cube;
        }
      }

      window.onload = () => {
        const stage = new Stage("#app", {
          // cameraType: "orthographi"
        });
        stage.run();

        window.stage = stage;
        new HelloWorldDemo(stage);
      };

    </script>

    <div id="app"></div>
  </head>

  <body>
  </body>

</html>

2、Stage.js

import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'

export class Stage {

  /**
   *
   * @param {*} container
   * @param {*} param
   * @param {* } param.disableControl
   * @param {* } param.cameraType "perspective" / "orthographi"
   * @param {boolean} param.needLight
   */
  constructor(container, param) {
    this.mouse = new THREE.Vector2()
    this.raycaster = new THREE.Raycaster();

    param = param || {}
    param.cameraType = param.cameraType || "perspective"
    param.needLight = param.needLight || true;

    this.fuArr = []
    this.viceCamera = null
    this.tmpTarget = new THREE.Vector3()
    this.orbitControls = null
    this.cameraHelper = null
    this.container = container;
    this.initFlag = false;
    // 场景
    this.scene = new THREE.Scene();
    this.scene.name = "moumade";

    if (param.needLight) {
      // 环境光
      var ambient = new THREE.AmbientLight(0xffffff, 0.5);
      ambient.name = "ambient";
      this.scene.add(ambient);

      let dirLight = new THREE.DirectionalLight(0xffffff, 0.5);
      dirLight.position.set(100, 100, 100);
      dirLight.name = "dirLight";
      this.scene.add(dirLight);
    }


    // 渲染器
    this.containerEle = document.querySelector(container);
    let vW = this.containerEle.clientWidth;
    let vH = this.containerEle.clientHeight;
    this.renderer = new THREE.WebGLRenderer({
      antialias: true,
      alpha: false,
      // preserveDrawingBuffer: true,
      // failIfMajorPerformanceCaveat: true,
    });
    // this.renderer.setClearColor(0x33334c, 1.0);
    this.renderer.setClearColor(0xf8f8f8, 1.0);
    // this.renderer.autoClear = true;
    this.renderer.setSize(vW, vH, false);
    this.renderer.setPixelRatio(window.devicePixelRatio);
    // console.error(vW, vH);

    this.containerEle.appendChild(this.renderer.domElement);
    if (param.cameraType == "perspective") {
      this.camera = new THREE.PerspectiveCamera(45, 1, 1, 500000000)
    } else if (param.cameraType == "orthographi") {
      this.camera = new THREE.OrthographicCamera(-vW / 2, vW / 2, -vH / 2, vH / 2, 0.1, 10000)
    }

    this.camera.lookAt(0, 0, 0)
    this.camera.name = "camera";
    this.scene.add(this.camera);
    this.handleResize = this.handleResize.bind(this)
    this._loop = this._loop.bind(this)
    window.addEventListener("resize", this.handleResize);

    this._isRun = true;
    // window.addEventListener("pointerdown", (event) => {
    //   this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    //   this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
    //   this.raycaster.setFromCamera(this.mouse, this.camera)
    //   const intersects = this.raycaster.intersectObjects(this.scene.children);
    //   console.error(intersects[0].point);

    // });
    this.handleResize();
    if (param && param.disableControl) {

    } else {
      this.initControls();
    }
    this.camera.position.set(0, 0, 1000)

    if (!param.disableAxis) {
      // let axis = new THREE.AxesHelper(10000000);
      // this.scene.add(axis);
      // this.axis = axis;
    }


    // @ts-ignore
    // this.stats = new Stats();
    // this.stats.domElement.style.position = 'absolute';
    // this.stats.domElement.style.left = '0px';
    // this.stats.domElement.style.top = '0px';
    // this.stats.domElement.style.width = '100px';
    // this.stats.domElement.id = 'stats';
    // this.containerEle.appendChild(this.stats.dom);

    this._loop()
  }

  initControls() {
    let control = new OrbitControls(this.camera, this.renderer.domElement);
    this.control = control
    // 使动画循环使用时阻尼或自转 意思是否有惯性
    control.enableDamping = true;
    //动态阻尼系数 就是鼠标拖拽旋转灵敏度
    control.dampingFactor = 0.35;
    //是否可以缩放
    control.enableZoom = true;
    control.zoomSpeed = 0.35;
    //是否自动旋转
    control.autoRotate = false;
    //设置相机距离原点的最远距离
    // control.minDistance = 22; //1000
    //设置相机距离原点的最远距离
    // control.maxDistance = 50; //3000
    //是否开启右键拖拽
    // control.enablePan = false;
  }

  handleResize() {
    // 获取新的大小
    let vpW = this.containerEle.clientWidth;
    let vpH = this.containerEle.clientHeight;
    // 设置场景
    this.renderer.domElement.width = vpW;
    this.renderer.domElement.height = vpH;
    this.renderer.setSize(this.containerEle.clientWidth, this.containerEle.clientHeight);
    // 设置相机
    (this.camera).aspect = vpW / vpH;
    this.camera.updateProjectionMatrix();
  }


  run() {
    // this._loop()
    this._isRun = true;
  }

  stop() {
    this._isRun = false;
  }

  addViceCamera(viceCamera) {
    this.viceCamera = viceCamera
  }

  // setRender(v: any) {
  //   this.state = v
  // }
  onUpdate(fu) {
    this.fuArr.push(fu)
  }

  _loop() {
    // this.stats.update()
    this.camera.updateProjectionMatrix();
    this.camera.updateMatrixWorld()
    this._isRun !== false && this.renderer.render(this.scene, this.camera);

    this.fuArr.forEach(fun => {
      fun()
    });
    this.control && this.control.update()
    requestAnimationFrame(this._loop)
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/704846.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

专利优先权应在什么时候提出

专利优先权要求应当在3个月内提交第一次提出的专利申请文件的副本&#xff1b;未提出书面声明或者逾期未提交专利申请文件副本的&#xff0c;视为未要求优先权。 申请人就相同主题的发明或实用新型在外国第一次提出专利申请之日起十二个月内&#xff0c;或者就相同主题的外观设…

【STM32智能车】智能车专题知识补充

【STM32智能车】智能车专题知识补充 智能车专题智能车的定义和发展历程。智能车的特点和优势。智能车的关键技术智能车的应用场景&#xff0c;如出租车、物流配送、公共交通等。智能车在环境保护、交通安全、经济发展等方面的作用。智能车发展面临的挑战和机遇 智能车专题 本专…

使用 Elasticsearch 1

了解如何创建索引&#xff0c;添加&#xff0c;删除&#xff0c;更新文档 参考文档 开始使用 Elasticsearch 1 本文用到Elasticsearch和Kibana 可以看之前的两篇先安装好 Elasticsearch 安装 Kibana安装 Elasticsearch 里的接口都是通过 REST 接口来实现的。 GET 读取数…

Scrapy框架之MongoDB通过配置文件管理参数--Linux安装MongoDB--图形管理工具

目录 MongoDB通过配置文件 问题 解决方案 步骤 提示 Linux安装MongoDB 环境 下载依赖与安装包 解压安装 MongoDB GUI管理工具 独立软件GUI软件 Robo 3T使用 VSCode集成GUI插件 MongoDB通过配置文件 问题 启动MongoDB时&#xff0c;编写参数太麻烦 解决方案 通过配…

【PCL】(三)读写PCD文件

文章目录 &#xff08;三&#xff09;读写PCD文件写读 &#xff08;三&#xff09;读写PCD文件 写 首先&#xff0c;创建一个名为pcd_write.cpp的文件&#xff0c;并在其中写入以下代码&#xff1a; #include <iostream> #include <pcl/io/pcd_io.h> #include &…

【项目实战】大文件断点续传,搞起

今天给大家分享的又是一篇实战文章&#xff0c;也是最近私活里遇到的&#xff0c;万能的互联网给了我办法&#xff0c;分享一下。 背景 最近接到一个新的需求&#xff0c;需要上传2G左右的视频文件&#xff0c;用测试环境的OSS试了一下&#xff0c;上传需要十几分钟&#xff…

Session

什么是Session&#xff1f; 服务器会给每个用户&#xff08;浏览器&#xff09;创建一个Session对象。一个Session独占一个浏览器&#xff0c;只要浏览器没有关闭&#xff0c;Session就一直存在。用户登陆后&#xff0c;整个网站都可以访问&#xff01;&#xff08;保存用户的…

掌握imgproc组件:opencv-直方图与匹配

直方图与匹配 1. 图像直方图概述2.直方图的计算与绘制2.1 计算直方图&#xff1a;calcHist()函数2.2 找寻最值&#xff1a;minMAxLoc()函数2.3 示例程序&#xff1a;绘制H-S直方图 3.直方图对比3.1 对比直方图&#xff1a;compareHist()函数3.2 示例程序&#xff1a;直方图对比…

Dubbo接口级服务发现-数据结构

目录 Dubbo服务治理易用性的原理&#xff1a; URL地址数据划分&#xff1a; Dubbo接口级服务发现---易用性的代价 Proposal&#xff0c;适应云原生、更大规模集群的服务发现类型。 Dubbo3应用级服务发现---基本原理 Dubbo负载均衡机制 常规负载均衡算法 负载均衡策略&am…

leetcode526. 优美的排列(回溯算法-java)

优美的排列 leetcode526. 优美的排列题目描述接替思路代码演示: 动态规划专题 leetcode526. 优美的排列 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/beautiful-arrangement 题目描述 假设有从 1 到 n 的 n 个整数。用…

【Python 随练】判断一个5位数是否为回文数

题目&#xff1a; 一个 5 位数&#xff0c;判断它是不是回文数。即 12321 是回文数 &#xff0c;个位与万位相同&#xff0c;十位与千位相同。 简介&#xff1a; 在本篇博客中&#xff0c;我们将解决一个编程问题&#xff1a;判断一个5位数是否为回文数。回文数是指从左到右…

数字IC前端学习笔记:近期最少使用(LRU)算法

相关文章 数字IC前端学习笔记&#xff1a;LSFR&#xff08;线性反馈移位寄存器&#xff09; 数字IC前端学习笔记&#xff1a;跨时钟域信号同步 数字IC前端学习笔记&#xff1a;信号同步和边沿检测 数字IC前端学习笔记&#xff1a;锁存器Latch的综合 数字IC前端学习笔记&am…

Java新特性-Functon接口

Java新特性-Functon接口 ⭐⭐⭐⭐⭐⭐ Github主页&#x1f449;https://github.com/A-BigTree 笔记链接&#x1f449;https://github.com/A-BigTree/Code_Learning ⭐⭐⭐⭐⭐⭐ Spring专栏&#x1f449;https://blog.csdn.net/weixin_53580595/category_12279588.html Sprin…

使用CRM系统如何让你的企业受益

随着市场的竞争日益加剧&#xff0c;企业需要更好地管理客户关系和提高销售。为此&#xff0c;很多企业已经开始使用CRM系统。CRM系统是一种管理客户关系的工具&#xff0c;可以帮助企业更好地了解客户需求&#xff0c;提高销售效率&#xff0c;提高客户满意度和忠诚度等。在这…

【ARM AMBA APB 入门 2 -- Debug APB总线介绍】

文章目录 1.1 DEBUG APB 介绍1.1.1 Debug APB interface 1.2 Debug APB 与 APB 的区别 1.1 DEBUG APB 介绍 ARM Debug APB是一种用于调试ARM处理器的总线协议。它是一种简化的、低功耗的调试接口&#xff0c;用于与处理器内部的调试逻辑进行通信。 ARM Debug APB具有以下特点…

使用Py2neo构建知识图谱(概念与实现)

知识图谱是一种用于描述实体之间关系的图形化知识表示方法&#xff0c;它将实体、属性和关系组织成一个大型的、半结构化的知识库。知识图谱的应用非常广泛&#xff0c;包括语义搜索、智能问答、个性化推荐、内容分发等领域。 知识图谱的构建方法有很多种&#xff0c;其中比较…

基于SpringBoot和Vue的医疗设备管理系统的设计与实现(源码+文档+报告)

伴随着网络技术的发展&#xff0c;网络巨头们也在各自的行业中展开了激烈的竞争。网络技术已经渗透到了社会的各个角落&#xff0c;移动支付、远程医疗和健康管理等多种网络技术的普及也日益广泛。同时&#xff0c;网络产业的崛起也极大地影响了传统产业。对医疗设备管理系统的…

Axure设计之动态柱状图教程(中继器)

中继器作为复杂的元件&#xff0c;通常被用来制作“高保真”的动态原型&#xff0c;以达到良好的视觉效果和交互效果。本文将教大家通过AxureRP9工具如何使用中继器设计动态柱状图表。 一、案例效果 下载地址&#xff1a; https://download.csdn.net/download/u010709330/8797…

多元分类预测 | Matlab鹈鹕算法(POA)优化混合核极限学习机(HKELM)分类预测,多特征输入模型,POA-HKELM分类预测

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元分类预测 | Matlab鹈鹕算法(POA)优化混合核极限学习机(HKELM)分类预测,多特征输入模型,POA-HKELM分类预测 多特征输入单输出的二分类及多分类模型。程序内注释详细,直接替换数据就可以用。程序语言为matlab…