three.js的使用
以创建一个立方体为例
安装
安装three:npm i three
使用
引用
引入three以及three中自带的相机控件OrbitControls用以操控相机:
初始化场景
scene:场景所有three事物均在其中。
camera:使用PerspectiveCamera透视相机,参数需注意调整否则会看不见物体与场景,参数依次为:fov视场,即可看到的角度范围,aspect长宽比,通常为窗口长宽比,near近面,基于相机位置开始渲染场景的位置一般较小默认0.1,far远面,基于相机位置结束渲染场景的位置,过大会影响渲染效率默认1000。
renderer:渲染器,用于生成canvas及设置其参数,需要将其appendChild至dom中指定元素。
天空盒子
创建天空盒子(一个包裹场景物体的立方体,可随鼠标拖动而变化角度),其中六张立方体贴图对应的顺序是右、左、上、下、前、后,图片需是特别制作的全景图,否者场景世界会出现明显的拼接边角:
也可直接使用一张贴图作为场景的背景,但使用此法场景不会随着鼠标变换角度与缩放:
相机控件
创建相机控件,其中需将相机与渲染的canvas元素添加到控件OrbitControls中,可通过控件控制拖拽、缩放、阻尼、偏角、自转(此种自转方式区别于模型自转,模型自转是通过控制物体mesh的rotation实现自转,该文章使用的是模型自转)等:
光源
创建光源,可设置环境光、点光源,最终显示出的光影效果是通过各种光效一起计算后渲染出来的:
立方体
创建的mesh(可理解为创建的物体)都是要通过add添加到场景中的,而mesh中有geometry(几何体)与material(材质),立方体的geometry可以利用three的BoxGeometry,而material可以使用MeshLambertMaterial材质,该材质对光照有反应,用于创建暗淡的不发光的物体,自身可设置颜色,自身颜色不受环境的影响。也可给材质设置纹理map(需导入图片作为纹理):
持续渲染
对场景与相机进行持续渲染,其中requestAnimationFrame为请求动画帧,以60hz刷新(但在高刷新屏中会频繁触发),用户切换标签时会暂停渲染,节省cpu开销。鼠标控件需要在渲染中调用update()更新:
完整代码
点击查看代码
<template>
<div class="three-div">
<div id="container">
<!--画布的容器-->
</div>
</div>
</template>
<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; //鼠标控制
import cubeImg from "@/assets/img/cube.png";
import BgImg from "@/assets/img/bg.png";
import right from "@/assets/img/space/right.jpg";
import left from "@/assets/img/space/left.jpg";
import top from "@/assets/img/space/top.jpg";
import bottom from "@/assets/img/space/bottom.jpg";
import front from "@/assets/img/space/front.jpg";
import back from "@/assets/img/space/back.jpg";
export default {
components: {},
data() {
return {
scene: "", //场景
camera: "", //相机
renderer: "", //渲染器
mouseControls: "", //轨道控制
pointLight: "", //点光源
ambientLight: "", //环境光
cube: "", //立方体
cubeImg: cubeImg, //立方体贴图
};
},
mounted() {
this.init();
},
methods: {
//初始化场景
init() {
this.scene = new THREE.Scene(); //新建场景
let width = window.innerWidth; //窗口宽度
let height = window.innerHeight; //窗口高度
let k = width / height; //窗口宽高比
this.camera = new THREE.PerspectiveCamera(60, k, 0.1, 10); //透视相机
this.camera.position.set(0, 0, 2.5); //设置相机位置
//创建渲染器
this.renderer = new THREE.WebGLRenderer({
antialias: true, //抗锯齿
alpha: true,
});
this.renderer.setSize(width, height); //设置渲染区域尺寸
document
.getElementById("container")
.appendChild(this.renderer.domElement); //将画布添加到container中
let axes = new THREE.AxesHelper(1); //坐标系(辅助开发)
axes.rotation.x = 0.1;
// this.scene.add(axes);
this.createSkyBox();
// this.createUniverse();
this.createOrbitControls();
this.createLight();
this.createCube();
this.repeatRender();
},
//创建天空盒子
createSkyBox() {
//加载天空盒子纹理
let cubeTexture = new THREE.CubeTextureLoader().load(
[right,left,top,bottom,front,back]
);
this.scene.background = cubeTexture; //设置场景背景
},
//创建宇宙背景
createUniverse(){
let texture = new THREE.TextureLoader().load(BgImg);//加载背景贴图
this.scene.background = texture;//设置场景背景
},
//创建轨道控制
createOrbitControls() {
//没有缩放阻尼
this.mouseControls = new OrbitControls(
this.camera,
this.renderer.domElement
); //创建控件对象
this.mouseControls.enablePan = false; //右键平移拖拽
this.mouseControls.enableZoom = true; //鼠标缩放
this.mouseControls.minDistance = 2; //相机距离原点的距离范围
this.mouseControls.maxDistance = 5;
this.mouseControls.enableDamping = true; //滑动阻尼
this.mouseControls.dampingFactor = 0.1; //(默认.25)
this.mouseControls.maxPolarAngle = (Math.PI / 4) * 3; //y旋转角度范围
this.mouseControls.minPolarAngle = Math.PI / 4;
// this.mouseControls.autoRotate = true; //自转(相机)
// this.mouseControls.autoRotateSpeed = 5; //自转速度
},
//创建光源
createLight() {
this.ambientLight = new THREE.AmbientLight(0x666666); //设置环境光
this.scene.add(this.ambientLight); //将环境光添加到场景中
this.pointLight = new THREE.PointLight(0xffffff, 1, 0);
this.pointLight.position.set(200, 200, 200); //设置点光源位置
this.scene.add(this.pointLight); //将点光源添加至场景
},
//创建立方体
createCube() {
let geometry = new THREE.BoxGeometry(1, 1, 1); //几何体
//材质
let material = new THREE.MeshLambertMaterial({
map: new THREE.TextureLoader().load(this.cubeImg), //导入图片纹理
});
this.cube = new THREE.Mesh(geometry, material); //将几何体与材质添加到网格中
this.cube.rotation.set(10, 10, 0);
this.scene.add(this.cube); //将立方体网格添加到场景中
},
//重复渲染
repeatRender() {
//请求动画帧,屏幕每刷新一次调用一次,绑定屏幕刷新频率
requestAnimationFrame(this.repeatRender);
this.mouseControls.update(); //实时更新轨道控制
this.cube.rotation.y += .01;//以y为轴心的旋转角度每帧自加0.01
this.renderer.render(this.scene, this.camera); //将场景和相机进行渲染
},
},
};
</script>
<style scoped>
</style>
图片素材
天空盒子贴图
back.jpg:
bottom.jpg:
front.jpg:
left.jpg:
right.jpg:
top.jpg:
立方体贴图
cube.png:
three.js的使用的更多相关文章
- Vue.js 和 MVVM 小细节
MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,其核心是提供对View 和 ViewModel 的双向数据绑定,这使得ViewModel 的状态改变可以自 ...
- js学习笔记:操作iframe
iframe可以说是比较老得话题了,而且网上也基本上在说少用iframe,其原因大致为:堵塞页面加载.安全问题.兼容性问题.搜索引擎抓取不到等等,不过相对于这些缺点,iframe的优点更牛,跨域请求. ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- JS调用Android、Ios原生控件
在上一篇博客中已经和大家聊了,关于JS与Android.Ios原生控件之间相互通信的详细代码实现,今天我们一起聊一下JS调用Android.Ios通信的相同点和不同点,以便帮助我们在进行混合式开发时, ...
- jquery和Js的区别和基础操作
jqery的语法和js的语法一样,算是把js升级了一下,这两种语法可以一起使用,只不过是用jqery更加方便 一个页面想要使用jqery的话,先要引入一下jqery包,jqery包从网上下一个就可以, ...
- 利用snowfall.jquery.js实现爱心满屏飞
小颖在上一篇一步一步教你用CSS画爱心中已经分享一种画爱心的方法,这次再分享一种方法用css画爱心,并利用snowfall.jquery.js实现爱心满屏飞的效果. 第一步: 利用伪元素before和 ...
- node.js学习(三)简单的node程序&&模块简单使用&&commonJS规范&&深入理解模块原理
一.一个简单的node程序 1.新建一个txt文件 2.修改后缀 修改之后会弹出这个,点击"是" 3.运行test.js 源文件 使用node.js运行之后的. 如果该路径下没有该 ...
- JS正则表达式常用总结
正则表达式的创建 JS正则表达式的创建有两种方式: new RegExp() 和 直接字面量. //使用RegExp对象创建 var regObj = new RegExp("(^\\s+) ...
- 干货分享:让你分分钟学会 JS 闭包
闭包,是 Javascript 比较重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,很难从定义去理解它.因此,本文不会对闭包的概念进行大篇幅描述 ...
- JS核心系列:理解 new 的运行机制
和其他高级语言一样 javascript 中也有 new 运算符,我们知道 new 运算符是用来实例化一个类,从而在内存中分配一个实例对象. 但在 javascript 中,万物皆对象,为什么还要通过 ...
随机推荐
- yb课堂 核心数据库表字段设计和测试数据准备 《一》
设计对应的表字段(统一使用Innodb引擎,mysql5.7) video_banner video chapter episode video_order user 数据库脚本 CREATE TAB ...
- Solo 开发者周刊 (第5期):打破常规,探索技术新边界
这里会整合 Solo 社区每周推广内容.产品模块或活动投稿,每周五发布.在这期周刊中,我们将深入探讨开源软件产品的开发旅程,分享来自一线独立开发者的经验和见解.本杂志开源,欢迎投稿. 产品推荐 1. ...
- Vue 3 后端错误消息处理范例
1. 错误消息格式 前后端消息传递时,我们可以通过 json 的 errors 字段传递错误信息,一个比较好的格式范例为: { errors: { global: ["网络错误"] ...
- PHP集群session共享
集群的概念没有多复杂,其实就是多台电脑为了同一个目标在一起工作.在Web应用中,就是多个服务器提供一个站点的服务. 搭建PHP集群的第一步就是设置负载均衡. 默认情况下PHP是将session存在本地 ...
- 解决php提示Maximum execution time of 30 seconds exceeded错误
如何解决错误? 基本上,有3种方法可以处理此错误: 修改php配置文件php.ini文件 使用 ini_set() 函数 使用set_time_limit()函数 1)修改php配置文件php.ini ...
- django如何将查询结果的栏位和数值自动遍历出来
在Django中,MT003HModel.objects.all() 返回的是一个 QuerySet 对象,你可以使用迭代器来遍历其中的每个对象,然后访问对象的属性来获取栏位和数值. 以下是一个简单的 ...
- oeasy教您玩转vim - 49 - # 命令进阶
命令进阶 回忆上节课内容 我们上次研究vim的历史 为什么会有行编辑器这种东西 竟然是当年 没有显示器只有纸的时代的无奈之举 vim进化到今天 依然还有好多人使用 而且ssh连接的时候直接vim就 ...
- 【AppStore】IOS应用上架Appstore的一些小坑
前言 上一篇文章写到如何上架IOS应用到Appstore,其中漏掉了些许期间遇到的小坑,现在补上 审核不通过原因 5.1.1 Guideline 5.1.1 - Legal - Privacy - D ...
- redis复制replica
通过查看log信息即可观察主机是否与从机正确连接,一般来说主机上有succeeded就是可以了 可以通过info replication查看自己的身份 role:master connected_sl ...
- BI 工具如何助力市政设计公司实现数字化转型?
一.前言 近年来,国家出台多个政策文件来鼓励和发展数字化和智能化,如<十四五规划>提出要推进产业数字化转型.<交通强国建设纲要>提出要大力发展智慧交通.上海市发布的<关于 ...