在Vue中搭建Three.js环境(超详细、保姆级),创建场景、相机、渲染器《一》

目录

  • Three.js简介
  • 创建vue项目
  • 引入Three.js
  • 实际操作环节
    • 文件目录创建
    • 初始化场景、相机

Three.js简介

Three.js 是一款基于 WebGL的 JavaScript 3D 库,它封装了 WebGL API,为开发者提供了简单易用的 API 来在 Web 浏览器中展示 3D 图形。Three.js 提供了多种组件、方法和工具,用于创建和处理 3D 图形,使得开发者可以在 Web 浏览器中快速创建 3D 场景和动画,而不需要深入了解 WebGL 的底层实现。

简单来说:它就是一个绘制 3D 的 javaScript 轻量级框架;
能干什么:游戏,地图,智能工厂,智慧园区,360°模型 ,建筑家装,3d物联网 ,能干的东西太多了,不一一说了,自己想去吧。
官方网址:https://threejs.org

好了好了,介绍到这里就行了,已经够多了,官方的介绍很详细,来来来 步入正题…

创建vue项目

你不想用vue也可以,不强求,但我想用!!!

  1. 在合适的文件夹目录 1 下去打开cmd(windows小黑窗口)窗口或者Terminal(Mac终端),这俩不知道的话,就别往下看了。在弹出的窗口中输入以下命令,回车即可。
vue create demo

注: 啥啥啥?vue不是内部或外部命令?点我点我

  1. 选择VUE2,本讲解以VUE2来进行 2 ,所以选择VUE2。 上下键去选,选完以后回车。
    在这里插入图片描述
  2. 展示以下结果代表创建成果,没报错就是创建成功了。
    在这里插入图片描述

引入Three.js

  1. 使用WebStorm(你想用什么工具都可以,不强求)打开刚才创建的项目。
    在这里插入图片描述
  2. 在开发工具的Terminal中输入以下内容回车。
 npm install three

在这里插入图片描述

实际操作环节

文件目录创建

  1. 在src下创建js文件目录
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  2. 并创建ThreeJs.js文件
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

初始化场景、相机

  1. Three他是一个右手系的X、Y、Z,如下图所示:
    在这里插入图片描述

  2. 引入Three文件,创建ThreeJs的通用组件方法,使用构造器构建组件。

import * as THREE from 'three';
export default class ThreeJs{
    
    constructor(id){
        //根据传入的id,去获取他的dom节点,用来加载三维模型
        this.id=id;
        this.dom=document.getElementById(id);
    }
   
}
  1. 创建initThree方法,用来初始化场景,动画的宽高,和相机。
 initThree(){
        //创建场景scene
        this.scene=new THREE.Scene();
        //获取dom的宽和高
        this.width=this.dom.offsetWidth
        this.height=this.dom.offsetHeight;
        //创建相机,fov:视角 aspect:宽高比 near:近裁剪面 far:远裁剪面
        this.camera=new THREE.PerspectiveCamera(45,this.width/this.height,1,1000);
       	//设置相机位置
        this.camera.position.set(0,0,0);
    }

:相机的相关解释,这个必须要详细的介绍一下,这个很关键。也可以点击链接看官方文档 官方

序号相机含义
1ArrayCamera(摄像机阵列)ArrayCamera 用于更加高效地使用一组已经预定义的摄像机来渲染一个场景。这将能够更好地提升VR场景的渲染性能。一个 ArrayCamera 的实例中总是包含着一组子摄像机,应当为每一个子摄像机定义viewport(视口)这个属性,这一属性决定了由该子摄像机所渲染的视口区域的大小。
2Camera(摄像机)摄像机的抽象基类。在构建新摄像机时,应始终继承此类。
3CubeCamera(立方相机)创建6个渲染到WebGLCubeRenderTarget的摄像机。
4OrthographicCamera(正交相机)这一摄像机使用orthographic projection(正交投影)来进行投影。在这种投影模式下,无论物体距离相机距离远或者近,在最终渲染的图片中物体的大小都保持不变。这对于渲染2D场景或者UI元素是非常有用的。。
5PerspectiveCamera(透视相机)这一摄像机使用perspective projection(透视投影)来进行投影。这一投影模式被用来模拟人眼所看到的景象,它是3D场景的渲染中使用得最普遍的投影模式。
6StereoCamera(立体相机)双透视摄像机(立体相机)常被用于创建3D Anaglyph(3D立体影像) 或者Parallax Barrier(视差屏障)。
  1. 修改相机观看位置点位,默认让他看原点
this.camera.looAt(0,0,0)
  1. 追加webGL的渲染器,他是用来调用浏览器的GPU,去进行实时渲染(前提浏览器已经支持GPU)
 this.renderer=new THREE.WebGLRenderer({antialias:true,alpha:true,logarithmicDepthBuffer:true})

注: antialias:是否开启锯齿,alpha:是否开启透明,logarithmicDepthBuffer:是否开启对数深度缓存。

  1. 设置渲染器的像素比,设置渲染器的输出颜色,设置渲染器的大小。
   // 设置渲染器的像素比
   this.renderer.setPixelRatio(window.devicePixelRatio);
   //渲染器的输出颜色
   this.renderer.outputEncoding=THREE.sRGBEncoding;
   //设置渲染器的大小
   this.renderer.setSize(this.width,this.height);
  1. 将渲染器的dom元素,添加至我们div的dom元素中
    this.dom.append(this.renderer.domElement);
  1. 监听浏览器大小,去更新相机的矩阵
    // 监听浏览器大小,去更新相机的矩阵
    window.addEventListener('resize',()=>{
        // 更新相机的宽高比
        this.camera.aspect=this.dom.offsetWidth/this.dom.offsetHeight;
        this.camera.updateProjectionMatrix();
        //更新渲染器的大小
        this.renderer.setSize(this.dom.offsetWidth,this.dom.offsetHeight);
        if(this.cssRenderer){
            this.cssRenderer.setSize(this.dom.offsetWidth,this.dom.offsetHeight);
        }
    })
  1. initThree()方法完整版如下
    initThree(){
        //这个初始化的是场景
        this.scene= new THREE.Scene();
        this.width=this.dom.offsetWidth;
        this.height=this.dom.offsetHeight;
        this.camera= new THREE.PerspectiveCamera(45,this.width/this.height,1,1000);

        this.camera.position.set(0,0,0);
        this.camera.lookAt(0,0,0);

        //追加webGL的渲染器,他是用来调用浏览器的GPU,去进行实时渲染(前提浏览器已经支持GPU)
        //antialias:是否开启锯齿,alpha:是否开启透明,logarithmicDepthBuffer:是否开启对数深度缓存
        this.renderer=new THREE.WebGLRenderer({antialias:true,alpha:true,logarithmicDepthBuffer:true})
        // 设置渲染器的像素比
        this.renderer.setPixelRatio(window.devicePixelRatio);
        //渲染器的输出颜色
        this.renderer.outputEncoding=THREE.sRGBEncoding;
        //设置渲染器的大小
        this.renderer.setSize(this.width,this.height);
        //将渲染器的dom元素,添加至我们div的dom元素中
        this.dom.append(this.renderer.domElement);

        // 监听浏览器大小,去更新相机的矩阵
        window.addEventListener('resize',()=>{
            // 更新相机的宽高比
            this.camera.aspect=this.dom.offsetWidth/this.dom.offsetHeight;
            this.camera.updateProjectionMatrix();
            //更新渲染器的大小
            this.renderer.setSize(this.dom.offsetWidth,this.dom.offsetHeight);
            if(this.cssRenderer){
                this.cssRenderer.setSize(this.dom.offsetWidth,this.dom.offsetHeight);
            }
        })
    }
  1. 创建辅助对象方法
    /**
    * @name 
    * @author shaoqunchao
    * @date 2024/3/5 10:21
    * @description 初始化X,Y,Z轴的扶助对象
    * @update 2024/3/5 10:21
    **/
    initHelper(helperSize=1000){
        this.scene.add(new THREE.AxesHelper(helperSize));
    }
  1. 重写render方法,调用requestAnimationFrame去更新相机和场景。
   render(callback){
        callback();
        requestAnimationFrame(()=>this.render(callback));
    }
  1. 在项目中任意的vue下去引用该组件。
<template>
      <div style="width: 100%;height: 100%" id="threejs"></div>

</template>

<script>
import ThreeJs from "@/js/ThreeJs";
    let app,scene,camera,renderer;

export default {
  name: 'App',
  components: {

  },
    methods:{
      async init(){
          app=new ThreeJs("threejs");
          app.initThree();
          app.initHelper();
          renderer=app.renderer;
          scene=app.scene;
          camera=app.camera;
          app.render(()=>{
              renderer.render(scene,camera)
          })
      }
    },
    mounted() {
      this.init();
    }
}
</script>

<style>
    html, body {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
        overflow: hidden; /* 防止出现滚动条 */
    }
</style>

  1. 去运行项目,查看当前效果,可以看到现在是一个空白的页面,什么也没有。
    在这里插入图片描述
  2. 是因为我们将相机的位置放在了0,0,0的位置,所以目前是什么也展示不了的,需要调整相机的位置。
    在这里插入图片描述
  3. 再次运行项目,可以看到我们的X,Y,Z轴的辅助对象。
    在这里插入图片描述
  4. 此时用鼠标旋转,放大缩小,都是不管用的,是因为我们没有初始化控制器,现在我们进行初始化控制器。
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import {CSS3DRenderer} from "three/examples/jsm/renderers/CSS3DRenderer"    

/**
     * @name 初始化控制器
     * @author shaoqunchao
     * @date 2024/1/18 13:05
     * @description 轨道控制器,可以使得相机围绕目标进行轨道运动
     * @param enableZoom 设置控制器是否可以缩放,默认为true。
     * @param autoRotate 设置是否自动旋转,默认为false。
     * @param enableDamping 设置控制器阻尼,让控制器更有真实效果,默认为false。
     * @param dampingFactor 设置控制器阻尼系数,让控制器更有真实效果,默认为0。
     * @param minDistance 设置控制器最小距离,默认为1。
     * @param maxDistance 设置控制器最大距离,默认为300。
     * @param minAzimuthAngle 设置控制器最小旋转角度,默认为0。
     * @update 2024/1/18 13:05
     **/
    initController(enableZoom=true,autoRotate=false,enableDamping=false,dampingFactor=0,minDistance=1,maxDistance=1000,minAzimuthAngle=0){
        let width=this.dom.offsetWidth;
        let height=this.dom.offsetHeight;
        //这个Renderer是用来运行3维指标,相当于一个html页面去嵌入至模型中。
        this.labelRenderer=new CSS3DRenderer();
        this.labelRenderer.setSize(width,height);
        //用来调整html页面的样式,让他围绕模型点位时,不会有偏移。
        this.labelRenderer.domElement.style.position='absolute';
        this.labelRenderer.domElement.style.top=0;
        this.labelRenderer.domElement.style.pointerEvents="none";
        this.dom.appendChild(this.labelRenderer.domElement);


        this.controller=new OrbitControls(this.camera,this.renderer.domElement);
        //设置控制器是否可以缩放
        this.controller.enableZoom=enableZoom;
        //设置是否可以旋转
        this.controller.autoRotate=autoRotate;
        //设置控制器阻尼效果,让控制器有真实的效果,
        this.controller.enableDamping=enableDamping;
        //设置阻尼控制器的系数
        this.controller.dampingFactor=dampingFactor;
        //设置控制器放大的最小距离
        this.controller.minDistance=minDistance;
        //设置控制器缩小的最大距离
        this.controller.maxDistance=maxDistance;
        //设置控制器最小旋转角度
        this.controller.minAzimuthAngle=minAzimuthAngle;
    }
  1. 页面进行引用,然后在浏览器中进行测试。
    在这里插入图片描述

  1. 你觉得那个文件夹合适,那它就合适,大犟种,还真点开看啊 ↩︎

  2. 多余的解释 点我 ↩︎

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【字符串】【括号匹配】【广度优先】301. 删除无效的括号

作者推荐 【二分查找】【C算法】378. 有序矩阵中第 K 小的元素 本文涉及知识点 字符串 括号匹配 广度优先 LeetCode301 删除无效的括号 给你一个由若干括号和字母组成的字符串 s &#xff0c;删除最小数量的无效括号&#xff0c;使得输入的字符串有效。 返回所有可能的结果…

Linux Watchdog 机制是什么

当涉及到Linux操作系统的稳定性和可靠性时&#xff0c;Linux Watchdog机制是一个至关重要的议题。该机制旨在监控系统状态&#xff0c;确保在出现问题时采取适当的措施以维持系统的正常运行。本文将深入探讨Linux Watchdog机制的工作原理、应用范围以及如何配置和使用该机制来提…

2023年全国职业院校技能大赛 GZ073网络系统管理赛项 模块A:网络构建

2023年全国职业院校技能大赛 GZ073网络系统管理赛项 模块A:网络构建 卷II 一. 拓扑图 二.有线网络配置 三.无线网络配置 四.出口网络配置 二、有线配置 S1.txt S1#show running-config Building configuration... Current configuration : 5008 bytes! version RGOS 10…

html标签之表格标签,想学web开发

html 1&#xff0c;浏览器存储的方式有哪些 2&#xff0c;如何解决跨域的&#xff1f; 3&#xff0c;浏览器 cookie 和 session 的认识。 4&#xff0c;输入URL发生什么&#xff1f; 5&#xff0c;浏览器渲染的步骤 6&#xff0c;页面渲染优化 7&#xff0c;强制缓存和协商缓存…

蓝桥杯刷题(一)

一、 import os import sys def dps(s):dp [0] * len(s)dp[0] ord(s[0]) - 96if len(s) 1:return dp[-1]dp[1] max(ord(s[0]) - 96, ord(s[1]) - 96)for i in range(2, len(s)):dp[i] max(dp[i - 1], dp[i - 2] (ord(s[i])) - 96)return dp[-1] s input() print(dps(s))…

App前端开发跨平台框架比较:React Native、Flutter、Xamarin等

引言 移动应用开发领域的跨平台框架正在不断演进&#xff0c;为开发者提供更多选择。在本文中&#xff0c;我们将比较几个流行的跨平台框架&#xff1a;React Native、Flutter和Xamarin等。讨论它们的优缺点、适用场景以及开发体验。 第一部分 React Native: 优缺点、适用场景…

gRPC-第二代rpc服务

在如今云原生技术的大环境下&#xff0c;rpc服务作为最重要的互联网技术&#xff0c;蓬勃发展&#xff0c;诞生了许多知名基于rpc协议的框架&#xff0c;其中就有本文的主角gRPC技术。 一款高性能、开源的通用rpc框架 作者作为一名在JD实习的Cpper&#xff0c;经过一段时间的学…

【Python】深度学习基础知识——梯度下降详解和示例

尽管梯度下降&#xff08;gradient descent&#xff09;很少直接用于深度学习&#xff0c;但它是随机梯度下降算法的基础&#xff0c;也是很多问题的来源&#xff0c;如由于学习率过大&#xff0c;优化问题可能会发散&#xff0c;这种现象早已在梯度下降中出现。本文通过原理和…

【控制台警告】npm WARN EBADENGINE Unsupported engine

今天用webpack下载几个loader依赖&#xff0c;爆出了三个警告&#xff0c;大概的意思就是本地安装的node和npm的版本不是很匹配&#xff1f; 我的解决思路是&#xff1a; 先检查node和npm版本 然后去官网查找版本的对应 靠&#xff0c;官网404 Node.js (nodejs.org) 就找到…

第十二篇:学习python数据清洗

文章目录 一、啥是数据清洗二、将表格数据导入pandas中1. 准备工作2. 引入csv文件2.1 引入pandas库2.2 读取文件/修改名称3.2 快速浏览数据2.4 修改名字2.5 查找缺失值2.6 删除缺失值 3. 引入Excel文件3.1 引入pandas库3.2 读取Excel文件的人均GDP数据3.3 查看数据类型和non-nu…

【鸿蒙 HarmonyOS 4.0】弹性布局(Flex)

一、介绍 弹性布局&#xff08;Flex&#xff09;提供更加有效的方式对容器中的子元素进行排列、对齐和分配剩余空间。容器默认存在主轴与交叉轴&#xff0c;子元素默认沿主轴排列&#xff0c;子元素在主轴方向的尺寸称为主轴尺寸&#xff0c;在交叉轴方向的尺寸称为交叉轴尺寸…

六、软考-系统架构设计师笔记-软件工程基础知识

1、软件工程 软件工程是将系统化的、严格约束的、可量化的方法应用于软件的开发、运行和维护&#xff0c;即将工程化应用于软件并对上述方法的研究。 软件要经历从需求分析、软件设计、软件开发、运行维护&#xff0c;直至被淘汰这样的全过程&#xff0c;这个过程称为软件的生…

什么是聚簇索引与非聚集索引和区别?

什么是聚簇索引与非聚集索引和区别? 按物理存储分类:InnoDB的存储方式是聚集索引&#xff0c;MVISAM的存储方式是非聚集索引 test innodb.frm 测试 innodb.ibd Frame表结构 数据表索引数据 test myisam.frm ---->Frame表结构test myisam.MYD_---数据表数据test_myisam.MYl-…

HTML实体字符列表,必看

HTML、CSS、JS三大部分都起什么作用&#xff1f; HTML内容层&#xff0c;它的作用是表示一个HTML标签在页面里是个什么角色&#xff1b;CSS样式层&#xff0c;它的作用是表示一块内容以什么样的样式&#xff08;字体、大小、颜色、宽高等&#xff09;显示&#xff1b;JS行为层…

【论文笔记】Language Models are Unsupervised Multitask Learners

Language Models are Unsupervised Multitask Learners 回顾一下第一代 GPT-1 &#xff1a; 设计思路是 “海量无标记文本进行无监督预训练少量有标签文本有监督微调” 范式&#xff1b;模型架构是基于 Transformer 的叠加解码器&#xff08;掩码自注意力机制、残差、Layernorm…

【Unity】ABB CRB 15000 外部引导运动

一、RobotStudio控制器的文件系统和配置参数 HOME&#xff1a;控制器文件系统的根目录或起始点。配置&#xff1a;机器人控制器的配置设置和参数。外件信息&#xff1a;连接到机器人的外部组件的信息。I/O 系统&#xff1a;输入/输出系统&#xff0c;管理机器人和外部设备之间的…

.[[backup@waifu.club]].wis最近多发,数据库被加密了能恢复吗?

Wis勒索病毒是怎样加密文件的&#xff1f; WIS勒索病毒加密文件的过程主要依赖于强大的加密算法&#xff0c;通常是RSA或AES等对称或非对称加密算法。这些算法可以非常快速地将用户的文件加密&#xff0c;使得文件在没有正确密钥的情况下无法被正常读取或打开。技术服务号&…

C#与欧姆龙PLC实现CIP通讯

参考文档&#xff1a; 欧姆龙PLC使用-CSDN博客 CIP通讯介绍&#xff08;欧姆龙PLC&#xff09;-CSDN博客 使用NuGet添加引用&#xff1a;CIPCompolet 基础参考我的CIP协议介绍&#xff0c;默认TCP端口为&#xff1a;44818 类NXCompolet 类的功能可以在安装PLC开发软件后帮…

Mol2文件处理-拆分、合并、提取名称、计数与格式转换

欢迎浏览我的CSND博客&#xff01; Blockbuater_drug …点击进入 文章目录 前言一、Mol2文件合并二、Mol2文件拆分为含有单个分子的文件三、Mol2文件分子名称修改与提取3.1 分子名称修改去除空格3.2 文件名称提取 四、Mol2文件包含分子计数4.1 Mol2文件中分子计数4.2 分子计数传…

Pytorch学习 day03(Tensorboard、Transforms)

Tensorboard Tensorboard能够可视化loss的变化过程&#xff0c;便于我们查看模型的训练状态&#xff0c;也能查看模型当前的输入和输出结果 在Pycharm中&#xff0c;可以通过按住ctrl&#xff0c;并左键点击某个库来进入源文件查看该库的使用方法SummaryWriter是用来向log_dir…