⭐ 偶然看到自己很久以前记录的一些关于threejs的笔记,上学的时候其实就有这个习惯,学啥都得记个花里胡哨的笔记,好像写了就会的感觉,哈哈哈哈,笔记一大堆,其实从来都不会翻看,不晓得大家是不是这样。
❤ 首先说明:笔记就是笔记,都是随手写的一些东西,如果你对threejs感兴趣或者刚刚入门的兄弟姐妹倒是可以看看。
了解threejs
threejs 是 javascript 编写的一个第三方库,是一款运行在浏览器中的 3d 引擎 threejs的三大组件:相机,渲染器和场景
相机
正交投影相机
⭐正交投影照相机获得的结果就像我们在数学几何学课上老师教我们画的效果,对于在三维空间内平行的线,投影到二维空间中也一定是平行的
`
var camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far)
`
透视投影投影相机
⭐使用透视投影照相机获得的结果是类似人眼在真实世界中看到的有“近大远小”的效果 最常用这种相机,有远近大小的感觉才是真3D的感觉不是
`
var camera=new THREE.PerspectiveCamera(远近,相机尺寸,一般为屏幕宽高,最近看到值,最远看到值)
`
场景
`
var scene = new THREE.Scene()
`
渲染器
`
var renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)//设置渲染区域尺寸
renderder.setClearColor(0xf99, 1)
document.body.appendChild(renderer.document)
renderer.render(scene, camera)
`
光源
⭐光源也是很重要的,世界里没有光,岂不是什么都看不见了,当然光也分为很多种光源。
光源大概有7种
基础光源
- 环境光(AmbientLight 会它的颜色会添加到整个场景和所有对象的当前颜色上)
- 点光源(PointLight 空间中的一点,朝所有的方向发射光线)
- 聚光灯光源(SpotLight 这种光源有聚光的效果,类似于台灯,吊灯,手电筒)
- 方向光(DirectionalLight 也称无限光,从这种光源发出的光线可以看作是平行的,例如太阳光)
特殊光源
-
半球光光源(HemisphereLight,可以为室内场景创建更加自然的光照效果,模拟反光面和光线微弱的天气)
-
面光源(AreaLight 使用这种光源可以指定散发光线的平面,而不是空间的一个点)
-
镜头炫光(LensFlare 这不是一种光源,但是通过该炫光可以为场景中的光源添加炫目的效果)
❤特殊光源懒得贴图了。
光源代码
`
var ambientLight = new THREE.DirectionalLight(0xffffff, 1);
ambientLight.position.set(0, 60, 50);
ambientLight.castShadow = true; //允许投射阴影
this.scene.add(ambientLight);
new THREE.AmbientLight(颜色) // 环境光
new THREE.PointLight(颜色, 强度, 距离) // 点光源
new THREE.DirectionalLight(颜色, 亮度) // 平行光
new THREE.SpotLight(颜色, 强度, 距离, 夹角, 衰减指数) // 聚光灯
`
几何体
⭐几何体内容大同小异,懒得细写了,列几种常见的几何体对象瞅瞅吧
- 立方体
`
new THREE.CubeGeometry(长, 宽, 高, 长的分割, 宽的分割, 高的分割) // 立方体
`
- 平面
`
new THREE.PlanGeometry(长, 宽, 长的分割, 宽的分割) // 平面
`
- 球体
`
new THREE.SphereGeometry(半径,经度切片,纬度分割,经度分割,经度跨过,纬度开始,纬度跨过) // 球体
`
- 圆形
`
new THREE.CircleGeometry(半径, 切片数, 开始, 跨过角度) // 圆形
`
- 圆台
`
new THREE.CylinderGeometry(顶部面积,底部面积,高,圆分割,高分割,是否没有顶面和底面) // 圆台
`
- 正四边形
`
new THREE.TetrahedronGeometry(半径, 细节) // 正四边形
`
- 正八边形
`
new THREE.OctahedronGeometry(半径, 细节) // 正八边形
`
- 正十二边形
`
new THREE.IconsahedronGeometry(半径, 细节) // 正十二边形
`
- 圆环面
`
new THREE.TorusGeometry(半径, 管道半径, 纬度分割, 经度分割, 圆环面的弧度) // 圆环面
`
-
自定义形状
⭐自定义形状其实不难,简单点理解就是通过画点,三个点可以拼成一个三角形,threejs的世界中的几何体其实都是通过三角形拼接而成的,可以先把需要的画的形状的点先添加好,在三个点拼成一个三角形的面,最种拼成一个整体的自定义形状。
`
var geometry = new THREE.Geometry()
geometry.vertices.push(new THREE.Vectory3(x, y, z)) // 点,其中 x、y、z 为坐标
geometry.faces.push(new THREE.Faces3(x, y, z)) // 面,其中 x、y、z 为点的数组的索引,三点确定一个面
`
材质
基本材质(MeshBasicMaterial)
`
new THREE.MeshBasicMaterial(options) // 基本材质
// options {} 可选。参数:
// visible:是否可见
// color:颜色
// wireframe: 是否渲染线而非面
// side:THREE.FrontSide 正面,THREE.BackSide 反面,THREE.DoubleSide 双面
// map: 贴图
`
光照材质(MeshLambertMaterial)
`
new THREE.MeshLambertMaterial(options) // Lambert 材质,适合光照
// ambient:反射能力
// emissive:自发光颜色
`
金属镜面材质(MeshPhongMaterial)
`
new THREE.MeshPhongMaterial() // Phong 材质,适合金属和镜面
// specular:光罩颜色
// shininess:光斑大小(值越大,光斑越小)
`
网格法向材质(MeshNormalMaterial)
⭐这个材质比较特殊,并不常用,可以计算光照、阴影时提供有用信息,从而为物体表面像素上色。简单的来说就是会通过光照等自动变化颜色。
`
new THREE.MeshNormalMaterial() // 方向材质
`
模型
OBJ模型
⭐OBJ模型是有模型和材质两部分的
需要引入的插件模块: 1、MTLLoader.js 2、OBJLoader.js
`
// OBJ模型导入
var mtlLoader = new THREE.MTLLoader()//材质loader
mtlLoader.load('/static/OBJ/铣槽机.mtl', function(materials) {
materials.preload()
var objloader = new THREE.OBJLoader()//模型loader
objloader.setMaterials(materials)//设置模型的材质
objloader.load('/static/OBJ/铣槽机.obj', function(mesh) {
mesh.position.set(0, 0, 0)模型在场景中的位置 x,y,x
mesh.scale.set(0.001, 0.001, 0.001)模型的缩放 x,y,z
scene.add(mesh)//将模型添加到场景种
})
})
`
物体点击事件
⭐使用 three.interaction.js 这个插件,就可以给物体创建事件啦,可以在创建模型或物体时添加需要的id等参数,点击时可以拿到物体的原型对象,找到存储的参数。
`
import{Scene,PerspectiveCamera,WebGLRenderer,Mesh,BoxGeometry,MeshBasicMaterial}from'three'
import { Interaction } from 'three.interaction'
const renderer = new WebGLRenderer({ canvas: canvasElement })
const scene = new Scene()
const camera = new PerspectiveCamera(60, width / height, 0.1, 100)
// new a interaction new一个Interaction 传入渲染器对象,场景对象,相机对象就可以啦
const interaction = new Interaction(renderer, scene, camera)
//创建一个盒子
const cube = new Mesh(
new BoxGeometry(1, 1, 1),//几何体
new MeshBasicMaterial({ color: 0xffffff })//材质
)
scene.add(cube)//将盒子添加进场景种
cube.cursor = 'pointer'//输入移入变小手
//常用的事件
cube.on('click', function(ev) {})//点击事件
cube.on('touchstart', function(ev) {})
cube.on('touchcancel', function(ev) {})
cube.on('touchmove', function(ev) {})
cube.on('touchend', function(ev) {})
cube.on('mousedown', function(ev) {})
cube.on('mouseout', function(ev) {})
cube.on('mouseover', function(ev) {})
cube.on('mousemove', function(ev) {})
cube.on('mouseup', function(ev) {})
//场景也可以添加事件
scene.on('touchstart', ev => {
console.log(ev)
})
scene.on('touchmove', ev => {
console.log(ev)
})
//移除事件
cube.off('touchmove', function(ev) {})
`
在物体上挖洞
⭐之前画过一个地铁站的场景3D,站厅站台上下两层结构的,需要地板上挖个洞,放电梯。类似这种需求的比如挖个门啊,窗户啊啥的应该也挺常见的,我觉得有模型还是用模型吧,自己画在挖洞其实挺烦,反正我是挺烦的,一点都不精致啊。
需要的插件:ThreeBSP.js
⭐简单的方式理解就是,用一个盒子覆盖在需要挖洞的盒子上,重叠的部分就是个洞。
`
//生成ThreeBSP对象
// planebox 需要挖洞的盒子
const plane1BSP = new ThreeBSP(planebox)
//cube1 他就是洞,其实就是个盒子,一个普普通通的几何体对象,设置好盒子的长宽高大小,就是洞的大小
const kong1BSP = new ThreeBSP(cube1)
//两个盒子结合了,洞产生了
const result1BSP = plane1BSP.subtract(kong1BSP)
const result1 = result1BSP.toMesh()
//为处理结果创建新的材质
// 注意:如果要给挖洞的盒子材质贴图的话,需要在此时贴图哦,就是挖完洞之后在贴图,提前贴好是不行的哦
let texture = this.initLoader('瓷砖.jpg', 60, 6)
result.material = new THREE.MeshLambertMaterial({
map: texture,
roughness: 10,
})
//添加到场景中
this.scene.add(result1)
--------
//此处时贴图加载方法 path:图片地址 W:横向加载几张 S:竖向加载几张
//比如一个长方形的地板帖瓷砖 横向不得比竖向贴的多么,根据实际情况整
initLoader (path, w, s) {
let loader = new THREE.TextureLoader()
let texture = loader.load(path)
texture.wrapS = texture.wrapT = THREE.RepeatWrapping
texture.repeat.set(w, s)
return texture
},
`
物体拖拽
需要引入的插件: DragControls.js
⭐总有客户或者老板想作妖,非要拖拽物体自定义场景,除了嘤嘤嘤,我还能做什么。
`
var box = new THREE.Mesh(
new THREE.BoxGeometry(10, 10, 10),
new THREE.MeshBasicMaterial({ color: 0x734777 })
)
scene.add(box)
// 添加平移控件
// var transformControls = new THREE.TransformControls(camera, renderer.domElement);
// scene.add(transformControls);
// 过滤不是 Mesh 的物体,例如辅助网格对象
var objects = []
// for (let i = 0; i < scene.children.length; i++) {
// if (scene.children[i].isMesh) {
// objects.push(scene.children[i]);
// }
// }
objects.push(box)
// 初始化拖拽控件
var dragControls = new THREE.DragControls(objects, camera, renderer.domElement)
// 鼠标略过事件
dragControls.addEventListener('hoveron', function(event) {
// 让变换控件对象和选中的对象绑定
transformControls.attach(event.object)
})
// 开始拖拽 controls是渲染器对象
dragControls.addEventListener('dragstart', function(event) {
controls.enabled = false
})
// 拖拽结束 controls是渲染器对象
dragControls.addEventListener('dragend', function(event) {
controls.enabled = true
})
`
❤ 感谢浏览~