写的网站 博客链接
1.npm `npm install three@0.106.2` vscode
2.下载three.js文件拖入项目
3.在需要定义three对象的js文件头写入import * as THREE from '../js/three.module.js';路径为自己的three.module.js文件的路径,这样就可以自动提示three.js中的函数和方法
(1)正交相机和透视相机(近大远小)
(2)相机的属性
<1>fov(field of view),可视角
<2>近切面,远切面,相机视锥体的远近限制范围
<3>aspect,宽高比,相机切面的宽高比例 w/h
示例:
//定义一个相机
var scene=new THREE.Scene();//场景
var camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,20);//透视投影相机
//透视相机,参数含义(可视角度,宽高比,近切面,远切面)
//fov 可视角度 field of view
//正交投影相机
var camera = new THREE.OrthographicCamera(
-window.innerWidth /2,
window.innerWidth / 2,
window.innerHeight / 2,
-window.innerHeight /2, 10, 1000
);
//正交相机,参数含义(左边界,右边界,上边界,下边界,近切面,远切面)
属性包含顶点数组 this.vertices,颜色信息 this.color,片面数据 this.faces
(1)线段
//声明和赋值
//1.线段
var geometry=new THREE.Geometry();
//geometry.vertices=[],是一个数组,值为顶点数据
geometry.vertices.push(
new THREE.Vector3(5,5,0),
new THREE.Vector3(-5,5,0),
)
var color1 = new THREE.Color(154/255,1,1,1),color2 = new THREE.Color(0xFF0000);//声明颜色信息
geometry.colors.push(color1, color2);//为顶点设置颜色
//使用定义好的顶点坐标,材质信息来构造几何体
var line = new THREE.Line(geometry, material, THREE.LineSegments);
scene.add(line);//将模型添加到场景中
(2)引擎提供的几何体
//声明和赋值
//圆柱体 参数列表,上平面半径,下平面半径,高度,圆被划分的次数,越大越接近圆
var geometry = new THREE.CylinderGeometry(100, 150, 400);
var material = new THREE.MeshLambertMaterial({ color: 0xFFFF00 });
var mesh=new THREE.Mesh(geometry,material)
mesh.position=new THREE.Vector3(0,0,0);
TODO:平移矩阵 表示一个顶点坐标沿着X Y Z轴分别平移Tx Ty Tz
| 1 0 0 Tx |
| 0 1 0 Ty |
| 0 0 1 Tz |
| 0 0 0 1 |
一个点的坐标是(x,y,z),假设沿着X Y Z轴分别平移Tx Ty Tz 平移后的坐标是(x+Tx,y+Ty,z+Tz)
矩阵和表示顶点坐标的向量进行乘法运算
| 1 0 0 Tx | | x | | x+Tx |
| 0 1 0 Ty | x | y | = | y+Ty |
| 0 0 1 Tz | | z | | z+Tz |
| 0 0 0 1 | | 1 | | 1 |
TODO:缩放矩阵
一个几何体的所有顶点坐标沿着X Y Z轴分别缩放矩阵Sx Sy Sz倍
顶点坐标缩放变换
| Sx 0 0 0 | | x | | x*Sx |
| 0 Sy 0 0 | x | y | = | y*Sy |
| 0 0 Sz 0 | | z | | z*Sz |
| 0 0 0 1 | | 1 | | 1 |
TODO:旋转矩阵
X轴 绕X轴旋转α度对应的旋转矩阵Rx
| 1 0 0 0 | | x | | x |
| 0 cosα -sinα 0 | x | y | = | cosα*y-sinα*z |
| 0 sinα cosα 0 | | z | | sinα*y+cosα*z |
| 0 0 0 1 | | 1 | | 1 |
Y轴 绕Y轴旋转α度对应的旋转矩阵Ry
| cosα 0 -sinα 0 | | x | | cosα*x+sinα*z |
| 0 1 0 0 | x | y | = | y |
| sinα 0 cosα 0 | | z | | -sinα*x+cosα*z |
| 0 0 0 1 | | 1 | | 1 |
Z轴 绕Z轴旋转α度对应的旋转矩阵Rz
| cosα -sinα 0 0 | | x | | cosα*x-sinα*y |
| sinα cosα 0 0 | x | y | | sinα*x+cosα*y |
| 0 0 1 0 | | z | | z |
| 0 0 0 1 | | 1 | | 1 |
js封装的矩阵的一些方法
绕x轴旋转.makeRotationX(theta)
绕y轴旋转.makeRotationY(theta)
绕z轴旋转.makeRotationZ(theta)
缩放.makeScale(Sx,Sy,Sz)
平移.makeTranslation(Tx,Ty,Tz)
剪切.makeShear
1.安装方法:
(1)vscode终端控制台运行npm i @tweenjs/tween.js@^18
(2)html引入node_modules/@tweenjs/tween.js/dist/tween.umd.js
详细案例见demo_3.js
2.使用new TWEEN.Tween(objs.rotation).to({y:360,z:360},10000).repeat(Infinity).start();来定义一个动画
objs为需要操作的属性,to(属性状态的最终值),10000为动画所需时间,Infinity为一直播放,可填入正正数表示动画
执行次数
3.在动画更新函数中调用TWEEN.update()
1.vscode终端控制台运行 npm install --save dat.gui
2.HTML界面引入脚本dat.gui/build/dat.gui.min.js
3.使用方法
var param;//使用param来控制相机的视角大小
function CreateGUI(){
var paramObj=function(){
this.fov=45;
}
param=new paramObj();
var gui=new dat.GUI;
gui.add(param,"fov",0,180).name("视角大小");
}
//在初始化的时候调用CreateGUI();函数来创建一个GUI
//在动画函数中调用ChangeFov();函数来改变相机的视角
//ChangeFov函数,将param的值赋给camera的fov(视角)参数,然后更新相机的矩阵
function ChangeFov(){
camera.fov=param.fov;
camera.updateProjectionMatrix();
}
1.在vscode终端控制台使用npm install stats.js安装插件
2.引入node_modules/stats.js/build/stats.min.js文件
3.初始化
var stats = new Stats();
stats.showPanel(0); // 0: fps, 1: ms, 2: mb, 3+: custom
stats.domElement.style.position = "absolute";
stats.domElement.style.left = "0px";
stats.domElement.style.right = "0px";
document.getElementById("canvas-frame").appendChild(stats.domElement);
4.检测性能,在检测代码的前后加上stats.begin();和stats.end();两个方法 //详细使用见demo_3.js
1.起初神创造天地
地是空虚混沌,渊面黑暗,神的灵运行在水面上
神说,要有光,于是就有了光,不好意思跑题了......
2.THREE.js提供的集中光源:
THREE.AmbientLight(环境光)
THREE.AreaLight(区域光)
THREE..DirectionalLight(方向光)
THREE.SpotLight(聚光灯)
THREE.PointLight(点光源) new THREE.PointLight(0xFFFF00,1,100,0.5);
点光源参数列表含义,光照颜色,光照强度,点光源的最大距离,到最大距离的衰减值
3.例:light = new THREE.AmbientLight(0xFFFF00,1);参数列表:光照颜色,光照强度
1.引入方法,<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
2.在HTML界面引入
1.安装方法:需要先引入jquery.js,步骤见第八步
(1)vscode终端控制台运行npm install spectrum-colorpicker,之后运行npm install -g grunt-cli
(2)html添加<script src="spectrum.js"></script>
<link rel="stylesheet" type="text/css" herf="spectrum.css"></link>
详细案例见demo_6.html
(3)代码:
$("#color-input-diy").spectrum({
color: "red",//初始化颜色
showInput: true,//显示输入
//allowEmpty:true,//允许为空,显示清楚颜色按钮
clickoutFiresChange: false,//单击选择器外部,如果颜色有改变则应用
containerClassName: "full-spectrum",
showInitial: true,//显示初始颜色,提供现在选择的颜色和初始颜色对比
showPalette: true,//显示选择器面板,即左侧有按钮的面板
showSelectionPalette: true,//记住选择过的颜色
showAlpha: true,//显示透明度选择
maxPaletteSize: 7,//记住选择过的颜色的最大数量
cancelText: "取消",//取消按钮,按钮文字
chooseText: "确定",//选择按钮,按钮文字
noColorSelectedText: "无颜色选择",//清除,按钮文字
preferredFormat: "hex",//输入框颜色格式,(hex十六进制,hex3十六进制可以的话只显示3位,hsl,rgb三原色,name英文名显示)
localStorageKey: "spectrum.demo",//把选择过的颜色存在浏览器上
//选择器右边面板移动时触发
move: function (color) {
updateBorders(color);
},
//选择器面板显示时触发
show: function () {
},
//选择器面板显示之前触发,返回false时不显示
beforeShow: function () {
},
//关闭面板或点击选择按钮,颜色变化时触发
change:function(){
},
//选择器面板隐藏时触发
hide: function (color) {
updateBorders(color);
},
//调色选择器面板显示的颜色
palette: [
["rgb(0, 0, 0)", "rgb(67, 67, 67)", "rgb(102, 102, 102)", "rgb(153, 153, 153)","rgb(183, 183, 183)",
"rgb(204, 204, 204)", "rgb(217, 217, 217)", "rgb(239, 239, 239)", "rgb(243, 243, 243)", "rgb(255, 255, 255)"],
["rgb(152, 0, 0)", "rgb(255, 0, 0)", "rgb(255, 153, 0)", "rgb(255, 255, 0)", "rgb(0, 255, 0)",
"rgb(0, 255, 255)", "rgb(74, 134, 232)", "rgb(0, 0, 255)", "rgb(153, 0, 255)", "rgb(255, 0, 255)"],
["rgb(230, 184, 175)", "rgb(244, 204, 204)", "rgb(252, 229, 205)", "rgb(255, 242, 204)", "rgb(217, 234, 211)",
"rgb(208, 224, 227)", "rgb(201, 218, 248)", "rgb(207, 226, 243)", "rgb(217, 210, 233)", "rgb(234, 209, 220)"],
["rgb(221, 126, 107)", "rgb(234, 153, 153)", "rgb(249, 203, 156)", "rgb(255, 229, 153)", "rgb(182, 215, 168)",
"rgb(162, 196, 201)", "rgb(164, 194, 244)", "rgb(159, 197, 232)", "rgb(180, 167, 214)", "rgb(213, 166, 189)"],
["rgb(204, 65, 37)", "rgb(224, 102, 102)", "rgb(246, 178, 107)", "rgb(255, 217, 102)", "rgb(147, 196, 125)",
"rgb(118, 165, 175)", "rgb(109, 158, 235)", "rgb(111, 168, 220)", "rgb(142, 124, 195)", "rgb(194, 123, 160)"],
["rgb(166, 28, 0)", "rgb(204, 0, 0)", "rgb(230, 145, 56)", "rgb(241, 194, 50)", "rgb(106, 168, 79)",
"rgb(69, 129, 142)", "rgb(60, 120, 216)", "rgb(61, 133, 198)", "rgb(103, 78, 167)", "rgb(166, 77, 121)"],
["rgb(133, 32, 12)", "rgb(153, 0, 0)", "rgb(180, 95, 6)", "rgb(191, 144, 0)", "rgb(56, 118, 29)",
"rgb(19, 79, 92)", "rgb(17, 85, 204)", "rgb(11, 83, 148)", "rgb(53, 28, 117)", "rgb(116, 27, 71)"],
["rgb(91, 15, 0)", "rgb(102, 0, 0)", "rgb(120, 63, 4)", "rgb(127, 96, 0)", "rgb(39, 78, 19)",
"rgb(12, 52, 61)", "rgb(28, 69, 135)", "rgb(7, 55, 99)", "rgb(32, 18, 77)", "rgb(76, 17, 48)"]
]
});
function updateBorders(color) {
//hexColor表示上次调色板显示的颜色
var hexColor = "transparent";
//如果当前设置颜色,则将颜色设置为当前颜色,否则,如果没有点击确定,则将颜色恢复为上次选择的颜色
if(color) {
hexColor = color.toHexString();
}
//如果没有下面这行代码,点击选择器面板时,即使不点击保存,也会造成input框中的值改变
$("#docs-content").css("border-color", hexColor);
}
1.纹理的基本属性:image(图片),wrapS(回环方式),offset(偏移)
2.Three.js中的纹理对象,使用THREE.Texture(image,mapping,wrapS,wrapT,magFilter,minFilter,format,type,anisotropy)
参数列表:image:图片类型,使用ImageUtils来加载
mapping:定义图片映射到模型上的方式
wrapS:表示x轴的纹理回环方式,即纹理宽度小于需要的贴图宽度时,平面剩下的地方应当如何进行贴图
wrapT表示y轴的纹理回环方式
3.纹理的加载方式,使用THREE.TextureLoader()来加载
4.cross-origin交叉域问题,浏览器无法读写本地文件,所以本地的图片在浏览器上不能直接访问到
5.加载的图片尺寸应为2的次方数
步骤:(例:创建一个三角形)
//1.需要先的定义一个空的几何体对象
var obj;
var geometry=new THREE.Geometry();//自定义几何体
var material=new THREE.MeshBasicMaterial({
vertexColors:THREE.VertexColors,
//color:0x00FF00,
wireframe: false,//该参数的含义为显示线框
});
//2.定义顶点
var p1=new THREE.Vector3(0,0,0);
var p2=new THREE.Vector3(0,200,0);
var p3=new THREE.Vector3(200,0,0);
//3.将顶点放置到几何体空间中
geometry.vertices.push(p1);
geometry.vertices.push(p2);
geometry.vertices.push(p3);
//4.为几何体新建面片,并为面片添加颜色
var color1 = new THREE.Color(0xFF0000);
var color2 = new THREE.Color(0x00FF00);
var color3 = new THREE.Color(0x0000FF);
var face=new THREE.Face3(0,1,2);//新建面片
//为面片顶点添加颜色
face.vertexColors[0] = color1;
face.vertexColors[1] = color2;
face.vertexColors[2] = color3;
geometry.faces.push(face)//将面片赋予几何体
Loder的执行是异步的,所以在使用加载的对象时需要先进行判空
加载obj格式模型的步骤,需要引入OBJLoader.js(用于加载obj文件),MTLLoader.js(用于加载材质文件)文件
详细见demo_13.js案例
//创建MTL加载器
var mtlLoader = new THREE.MTLLoader();
//设置文件路径
mtlLoader.setPath('../js/models/obj/');
//加载mtl文件
mtlLoader.load('female02.mtl', function (material) {
//创建OBJ加载器
var objLoader = new THREE.OBJLoader();
//设置当前加载的纹理
objLoader.setMaterials(material);
objLoader.setPath('../js/models/obj/');
objLoader.load('female02.obj', function (object) {
//添加阴影
object.traverse(function (item) {
if (item instanceof THREE.Mesh) {
item.castShadow = true;
item.receiveShadow = true;
}
});
//缩放
object.scale.set(.3, .3, .3);
scene.add(object);
})
});
// OBJ文件是一种标准的3D模型文件格式,适合3D模型之间的互相转换
// OBJ文件的格式:
// #代表注释行,一般写模型生成的软件,解析时会被忽略掉
// 下面的行首字符为关键字,代表法线,材质,点,纹理等
// o:代表对象名称
// v:几何体顶点
// vt:贴图坐标点
// vn:顶点法线
// vp:参数空格顶点
// deg:度
// l:线
// f:面 后面三行数据意义:(顶点索引/UV坐标的索引/法线的索引)循环三次,表示三角形面片三个点的数据
// curv:曲线
// curv2:2D曲线
// surf:表面
// mtllib:表示模型使用的材质
// 例:obj文件的数据(一个双面的四边形面片)
含义:v代表四个顶点的xyz坐标,f表示以怎样的顺序去包围这个面,顺序决定右手坐标系下面的正反面
# custom shap
v -0.58 0.84 0
v 2.68 1.17 0
v 2.84 -2.03 0
v -1.92 -2.98 0
f 4 3 2 1
f 1 2 3 4
//Three.js通过正则表达式来解析obj格式的文件 由OBJLoader.js来处理
//正则表达式在js中的使用方法
var str1="sxo05110511"
var str2="wkp01220122"
/正则表达式字符串/gm.test(str1) //返回true或者false
//使用正则表达式解析obj格式文件的每一行,拆分成顶点坐标,法向量,uv坐标,再使用BufferGeometry来转化成面片
//最后将多个转化的面片拼接成几何体,再转化为object对象即可加载到场景中
//构造函数
THREE.Raycaster=function (origin,direction,near,far)
// 参数的含义 origin:光线发射出去的地方 direction:归一化的方向向量 near:光线发射最近的地方 far:光线发射最远的地方
// 不传参数会默认起始位置和方向都为原点
var raycaster = new THREE.Raycaster();
// 根据在屏幕的二维位置以及相机的矩阵更新射线的位置,第一个参数为归一化的设备坐标(xyz在-1到1之间),第二个参数光线起源的位置
raycaster.setFromCamera(mouse, camera);//得到一个由相机指向鼠标的光线向量
// 参数为检测相交物体的数组
// 返回一个数组,为相交的对象的数组
// 增加第二个参数,可以遍历子子孙孙对象
var intersects = raycaster.intersectObjects(scene.children, true);
// intersects是返回的一个数组,如果当前位置没有可选中的对象,那这个数组为空,否则为多个对象组成的数组,排列顺序为距离屏幕的距离从近到远的顺序排列
// 数组的每一个子对象内包含:
// distance:距离屏幕的距离
// face:与射线相交的模型的面
// faceIndex:与射线相交的模型的面的下标
// object:与射线相交的模型对象
// point:射线与模型相交的点的位置坐标
// uv:与射线相交的模型的面的uv映射位置
// 1.解决思路:物体放置在一个组对象当中,然后旋转组对象
//使用rotateOnAxis(v1,0.1);来旋转的注意事项
//v1为旋转轴,必须进行归一化,否则绕轴旋转会改变物体的比例
var v1 = new THREE.Vector3(1,1,0).normalize();//旋转轴
mesh.rotateOnAxis(v1,0.1);
//加载的模型objloader自定义材质
objLoader.load('xxx.obj',
//onload函数
function (object) {
object.scale.set(0.3,0.3,0.3)
//设置材质
for (let i = 0; i < object.children.length; i++) {
var mat=object.children[i].material
mat.color.set(0xffffff)
mat.wireframe=true
}
scene.add(object);
}
)
mesh.geometry.verticesNeedUpdate = true;//只有将这个属性设置为true,GPU才会重新计算顶点的位置,新的图形才会被渲染
//贝塞尔曲线,由两个端点的组成,中间有若干控制点,曲线必须经过两端端点,不必经过中间控制点,但是中间控制点起到影响曲线路径的效果
//这样的曲线被称作贝塞尔曲线
//一阶贝塞尔曲线:中间无控制点的曲线(线段)
一阶贝塞尔曲线公式:B(t) = (1 - t) * P0 + t * P1 ,t∈[0,1]
//二阶贝塞尔曲线:中间一个控制点
二阶贝塞尔曲线公式:B(t) = (1 - t)² * P0 + 2 * t * (1 - t) * P1 + t² * P2 ,t∈[0,1]
//三阶贝塞尔曲线:中间两个控制点
三阶贝塞尔曲线公式:B(t) = (1 - t)³ * P0 + 3 * P2 * t² * (1 - t) + t³ * P3 ,t∈[0,1]
//贝塞尔曲线在THREE.js中
二阶:
circleShape.moveTo(circleRadius, 0);//端点1
//参数为控制点和端点2
circleShape.quadraticCurveTo(0, circleRadius, -circleRadius, 0);
三阶:
//需要由端点1调用,参数为控制点1,2和端点2
THREE.Path.portotype.bezierCurveTo=function (aCP1x,aCP1y,aCP2x,aCP2y,aX,aY) {
}