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

news2025/1/16 19:04:56

目录

  • 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.coloradmin.cn/o/1492553.html

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

相关文章

【C#杂谈】在 .NET Framework 中使用新的C#语言特性

前排提示&#xff1a;提出一个可以让 [^1] 这中语法可以在.NET Framework运行时中使用的方法 众所都周知&#xff0c;.NET Framework&#xff08;以下简称 .NF&#xff09;作为一个被微软官方确认不在继续发布新特性的运行时&#xff0c;它所对应的C#语言版本被&#xff08;官方…

Unity使用UnityWebRequest读取音频长度不对的解决方法

在开发的过程中碰到这样一个问题&#xff0c;有的音频文件通过UnityWebRequest读取出来后&#xff0c;AudioClip的Length会不对&#xff0c;比如本身有7秒&#xff0c;读出来只有3秒。代码如下&#xff1a; IEnumerator TestEnumerator() {UnityWebRequest www UnityWebReque…

BERT学习【BERT的例子以及作用】

一、case 1.case1 多输入单输出。通过输入一个句子&#xff08;sequence&#xff09;&#xff0c;然后输出一个句子的分类&#xff08;这个句子是正向还是负向&#xff09;。将句子输入BERT&#xff0c;然后通过softmax输出分类。 2.case2 多输入多输出。输入一个句子&…

专业的安全数据交换系统,如何进行网间数据安全交换?

网络隔离是企业网络安全管理的重要组成部分&#xff0c;它有助于提高网络的整体安全性&#xff0c;保护企业资产和客户数据&#xff0c;同时满足法规合规要求。很多企业为了防止内部核心数据泄露&#xff0c;都实施了网络隔离&#xff0c;比如划分成内网、外网&#xff0c;有的…

安装R语言,完整教程

安装R语言&#xff0c;完整教程 介绍特点 应用场景和用户对象安装教程下载地址安装打开软件 介绍 R语言是一种用于统计分析和数据可视化的编程语言&#xff0c;广泛应用于学术研究、数据科学、商业分析等领域。它由新西兰奥克兰大学的Ross Ihaka和Robert Gentleman于1995年开发…

Ps:色阶

色阶 Levels命令用于改善图像的对比度和调整亮度/暗度平衡&#xff0c;通过操作图像的直方图来精细调整图像的阴影、中间调和高光。 Ps菜单&#xff1a;图像/调整/色阶 Adjustments/Levels 快捷键&#xff1a;Ctrl L Ps菜单&#xff1a;图层/新建调整图层/色阶 New Adjustment…

Acwing 周赛145 解题报告 | 珂学家 | 贪心构造

前言 整体评价 VP了这场比赛&#xff0c;偏简单吧。T3是道贪心构造题&#xff0c;卡语言&#xff0c;因为题和数都是从CF拿来的。 A. 平均成绩 思路: 模拟 这边有个小技巧&#xff0c;就是规避浮点运算。 可以左右侧都乘以3。 #include <bits/stdc.h>using namespac…

稀碎从零算法笔记Day9-LeetCode:最后一个单词的长度

题型&#xff1a;字符串、反转字符串 链接:58. 最后一个单词的长度 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 题目描述&#xff08;红字为笔者添加&#xff09; 给你一个字符串 s&#xff0c;由若干单词组成&#xff0c;单词前后用一些空格字符隔…

Linux Ubuntu 部署SVN

最近需要在ubuntu server上部署一个svn&#xff0c;记录 不需要特定版本 如果不需要特定版本&#xff0c;这样安装就是最简单的 sudo apt update然后开始安装 sudo apt install subversion等到安装完成之后执行查看版本命令&#xff0c;如果正常输出那就没问题了 svnadmin …

Rust 开发的高性能 Python 包管理工具,可替换 pip、pip-tools 和 virtualenv

最近&#xff0c;我在 Python 潮流周刊 中分享了一个超级火爆的项目&#xff0c;这还不到一个月&#xff0c;它在 Github 上已经拿下了 8K star 的亮眼成绩&#xff0c;可见其受欢迎程度极高&#xff01;国内还未见有更多消息&#xff0c;我趁着周末把一篇官方博客翻译出来了&a…

绝地求生:调整不同血雾颜色效果,显著提升抽靶击中时的反馈效果

嗨&#xff0c;我是闲游盒~ 有很多玩家在玩游戏时&#xff0c;游戏设置方面默认的偏多&#xff0c;其中就有击中敌人时&#xff0c;血雾颜色呈暗绿色&#xff0c;导致抽靶时不好判断是否击中敌人。 在补枪方面也有很大影响&#xff0c;尤其在植被茂密的地形中。 你看得出来被击…

EPSON RA8000CE (RTC模块)压电侠

RA8000CE是一个集成了32.768 kHz数字温度补偿晶体振荡器(DTCXO)的RTC模块。它包括各种功能&#xff0c;如具有闰年校正的秒到年时钟/日历&#xff0c;时间警报&#xff0c;唤醒计时器&#xff0c;时间更新中断&#xff0c;时钟输出和时间戳功能&#xff0c;可以在外部或内部事件…

【Photoshop2020版本】零基础笔记(一)

哈喽大家好~最近博客内容换方向了哈哈哈~换成“实用版”了。 今天给大家带来的是 PS 相关内容 其实我也是刚学PS&#xff0c;所以想着自己做笔记还不如发布出去&#xff0c;让大家都能看到&#xff0c;有兴趣的伙伴们&#xff0c;可以跟着我的笔记一块学习&#xff0c;这个专…

出现身份验证错误,无法连接到本地安全机构 顺利解决这个问题希望能帮助大家

出现身份验证错误&#xff0c;无法连接到本地安全机构&#xff0c;远程计算机&#xff1a;XX&#xff0c;这可能是由于密码过期&#xff0c;如果密码已过期请更新密码。 我们可以在系统属性中对远程进行设置&#xff0c;以解决远程桌面无法连接到本地安全机构这一问题。 步骤…

HTML常用的五种标签,太棒了

form表单细节 一、表单 1.表单 标签用于为用户输入创建 HTML 表单 2.表单能够包含 input 元素&#xff0c;比如文本字段、复选框、单选框、提交按钮等等。 3.表单还可以包含 menus、textarea、fieldset、legend 和 label 元素。 4.表单用于向服务器传输数据。 二、表单form 的…

大语言模型在科技研发与创新中的角色在快速变化

在技术研发与创新中&#xff0c;比如在软件开发、编程工具、科技论文撰写等方面&#xff0c;大语言模型可以辅助工程师和技术专家进行快速的知识检索、代码生成、技术文档编写等工作。在当今的软件工程和研发领域&#xff0c;尤其是随着大语言模型技术的快速发展&#xff0c;它…

算法46:动态规划专练(力扣198: 打家劫舍 力扣740:删除并获取点数)

打家劫舍问题&#xff1a; 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给定…

flutter框架优缺点,最新Android大厂高频面试题

部分面试常问的面试专题 一、Java篇 1.多线程并发&#xff1b; sleep 和 wait 区别join 的用法线程同步&#xff1a;synchronized 关键字等线程通信线程池手写死锁 2.Java 中的引用方式&#xff0c;及各自的使用场景 3.HashMap 的源码 4.GC(垃圾回收)是什么&#xff1f;如何…

运维随录实战(8)之搭建数据库

docker搭建mysql5.7 如果出现no matching manifest for windows/amd64 10.0.18363 in the manifest list entries错误,则将docker desktop的settings->Docker Engine中的experimental值设为true。 touch : 无法将“touch”项识别为 cmdlet、函数、脚本文件或可运行程序的…

is not valid JSON at JSON.parse

在后台读取一个文件里的JSON数据&#xff0c;转换成字符串返回给前端&#xff0c;前端使用JSON.parse转换JSON报错。在将JSON校验和压缩后发现前端还是转换失败。在返回结果的时候可以看见一个小红点 最后排查&#xff0c;不带BOM的识别是Java遗留的一个bug。 解决方案&#…