一、需求:让画布充满屏幕
camera.aspect
.aspect : Float
摄像机视锥体的长宽比,通常是使用画布的宽/画布的高。默认值是1(正方形画布)
camera.updateProjectionMatrix()
属性
请参阅其基类 Camera 来查看共有属性。
请注意,在大多数属性发生改变之后,你将需要调用.updateProjectionMatrix来使得这些改变生效。.updateProjectionMatrix () : null
更新摄像机投影矩阵。在任何参数被改变以后必须被调用。
方法通过监听 window中resize属性来观测窗口大小从而改变画布大小
const sizes = {
width: window.innerWidth,
height: window.innerHeight,
};
window.addEventListener('resize',function(event){
sizes.width=window.innerWidth;
sizes.height=window.innerHeight;
camera.aspect=sizes.width/sizes.height; //改变摄像机比例
camera.updateProjectionMatrix() //更新摄像机属性
renderer.setSize(sizes.width,sizes.height) //设置画布大小
})
二、设备像素比
window属性:devicePixelRatio
2018-04-03 10:54 更新
devicePixelRatio属性
该 Window 属性 devicePixelRatio 能够返回当前显示设备的物理像素分辨率与 CSS 像素分辨率的比率。此值也可以解释为像素大小的比率:一个 CSS 像素的大小与一个物理像素的大小的比值。简单地说,这告诉浏览器应该使用多少个屏幕的实际像素来绘制单个 CSS 像素。
这在处理标准显示与 HiDPI 或 Retina 显示之间的差异时很有用,它使用更多屏幕像素绘制相同对象,从而产生更清晰的图像。
当此值发生变化时(例如,如果用户将 window 拖到具有不同像素密度的显示器上),则无法通知该值。由于没有可用于检测像素密度变化的回调或事件,因此唯一的方法是定期检查其 devicePixelRatio 值是否已更改。不要经常这样做,否则会影响性能。
设置 像素比相同
renderer.setPixelRatio(Math.min(window.devicePixelRatio,2));
三、双击全屏
兼容写法
window.addEventListener('dblclick',function(){
const fullscreenElement=document.fullscreen || document.mozFullScreen || document.webkitIsFullScreen ||document.webkitFullScreen|| document.msFullScreen
if(!fullscreenElement){
if (canvas.RequestFullScreen) {
canvas.RequestFullScreen()
//兼容Firefox
} else if (canvas.mozRequestFullScreen) {
canvas.mozRequestFullScreen()
//兼容Chrome, Safari and Opera等
} else if (canvas.webkitRequestFullScreen) {
canvas.webkitRequestFullScreen()
//兼容IE/Edge
} else if (canvas.msRequestFullscreen) {
canvas.msRequestFullscreen()
}
}else{
console.log('取消')
if(document.exitFullScreen) {
document.exitFullScreen();
//兼容Firefox
} else if(document.mozCancelFullScreen) {
document.mozCancelFullScreen();
//兼容Chrome, Safari and Opera等
} else if(document.webkitExitFullscreen) {
document.webkitExitFullscreen();
//兼容IE/Edge
} else if(element.msExitFullscreen) {
element.msExitFullscreen();
}
}
})
四、立方几何体(BoxGeometry)
BoxGeometry是四边形的原始几何类,它通常使用构造函数所提供的“width”、“height”、“depth”参数来创建立方体或者不规则四边形。
构造器
BoxGeometry(width : Float, height : Float, depth : Float, widthSegments : Integer, heightSegments : Integer, depthSegments : Integer)
width — X轴上面的宽度,默认值为1。
height — Y轴上面的高度,默认值为1。
depth — Z轴上面的深度,默认值为1。
widthSegments — (可选)宽度的分段数,默认值是1。
heightSegments — (可选)宽度的分段数,默认值是1。
depthSegments — (可选)宽度的分段数,默认值是1。
例:
const geometry = new THREE.BoxGeometry(1, 1, 1,2,1,1);
const material = new THREE.MeshBasicMaterial({ color: 0xff0000,wireframe:true });
基础网格材质(MeshBasicMaterial)
一个以简单着色(平面或线框)方式来绘制几何体的材质。
.wireframe : Boolean
将几何体渲染为线框。默认值为false(即渲染为平面多边形)。
立方缓冲几何体(BoxBufferGeometry)
这是BoxGeometry中的BufferGeometry接口。
构造器
BoxBufferGeometry(width : Float, height : Float, depth : Float, widthSegments : Integer, heightSegments : Integer, depthSegments : Integer)
width — X轴上面的宽度,默认值为1。
height — Y轴上面的高度,默认值为1。
depth — Z轴上面的深度,默认值为1。
widthSegments — (可选)宽度的分段数,默认值是1。
heightSegments — (可选)宽度的分段数,默认值是1。
depthSegments — (可选)宽度的分段数,默认值是1。
* 最好去使用 bufferGeometry 有更好的性能优化 *
Face3
在 Geometry 中被使用到的三角面片。这些三角面片会为所有标准几何体自动创建。 然而,如果你正在构建一个自定义几何体,你需要手动创建这些三角面片。
构造函数
Face3( a : Integer, b : Integer, c : Integer, normal : Vector3, color : Color, materialIndex : Integer )
a — 顶点 A 的索引。
b — 顶点 B 的索引。
c — 顶点 C 的索引。
normal — (可选) 面的法向量 (Vector3) 或顶点法向量队列。 如果参数传入单一矢量,则用该量设置面的法向量 .normal,如果传入的是包含三个矢量的队列, 则用该量设置 .vertexNormals
color — (可选) 面的颜色值 color 或顶点颜色值的队列。 如果参数传入单一矢量,则用该量设置 .color,如果传入的是包含三个矢量的队列, 则用该量设置 .vertexColors
materialIndex — (可选) 材质队列中与该面对应的材质的索引。
const faces=new THREE.Face3(0,1,2)
利用buffer来创建 网状物
BufferAttribute
这个类用于存储与BufferGeometry相关联的 attribute(例如顶点位置向量,面片索引,法向量,颜色值,UV坐标以及任何自定义 attribute )。 利用 BufferAttribute,可以更高效的向GPU传递数据。详情和例子见该页。
在 BufferAttribute 中,数据被存储为任意长度的矢量(通过itemSize进行定义),下列函数如无特别说明, 函数参数中的index会自动乘以矢量长度进行计算。构造函数
BufferAttribute( array : TypedArray, itemSize : Integer, normalized : Boolean )
array -- 必须是 TypedArray. 类型,用于实例化缓存。
该队列应该包含:itemSize * numVertices
个元素,numVertices 是 BufferGeometry中的顶点数目
itemSize -- 队列中与顶点相关的数据值的大小。举例,如果 attribute 存储的是三元组(例如顶点空间坐标、法向量或颜色值)则itemSize的值应该是3。
normalized -- (可选) 指明缓存中的数据如何与GLSL代码中的数据对应。例如,如果array是 UInt16Array类型,且normalized的值是 true,则队列中的值将会从 0 - +65535 映射为 GLSL 中的 0.0f - +1.0f。 如果array是 Int16Array (有符号),则值将会从 -32767 - +32767 映射为 -1.0f - +1.0f。若 normalized 的值为 false,则数据映射不会归一化,而会直接映射为 float 值,例如,32767 将会映射为 32767.0f.
const bufferGeometry=new BufferGeometry()
const positionsArray=new Float32Array([
0,0,0,
0,1,0,
1,0,0
])
const positionsAttribute=new THREE.BufferAttribute(positionsArray,3)
bufferGeometry.setAttribute('position',positionsAttribute)
const mesh = new THREE.Mesh(bufferGeometry, material);
scene.add(mesh);
通过 new Float32Array创建两个
const bufferGeometry=new BufferGeometry()
const positionsArray=new Float32Array([
0,0,0,
0,1,0,
1,0,0,
0.5,0.1,0.2,
0.8,0.1,0.3,
0.4,0.2,0.1,
])
const positionsAttribute=new THREE.BufferAttribute(positionsArray,3)
bufferGeometry.setAttribute('position',positionsAttribute)
创建多个(50)
const bufferGeometry=new BufferGeometry()
const count=50;
const positionsArray=new Float32Array(count*3*3);
for(let i=0;i<count*3*3;i++){
positionsArray[i]=Math.random()
}
const positionsAttribute=new THREE.BufferAttribute(positionsArray,3)
bufferGeometry.setAttribute('position',positionsAttribute)
完整代码
import "./style.css";
import * as THREE from "three";
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'
import gsap from 'gsap'
import { BufferGeometry } from "three";
const scene = new THREE.Scene();
// const geometry = new THREE.BoxGeometry(1, 1, 1,2,1,1);
const geometry = new THREE.Geometry();
const material = new THREE.MeshBasicMaterial({ color: 0xff0000,wireframe:true });
const sizes = {
width: window.innerWidth,
height: window.innerHeight,
};
// const vertex1=new THREE.Vector3(0,0,0);
// geometry.vertices.push(vertex1)
// const vertex2=new THREE.Vector3(0,1,0);
// geometry.vertices.push(vertex2)
// const vertex3=new THREE.Vector3(1,0,0);
// geometry.vertices.push(vertex3)
// const faces=new THREE.Face3(0,1,2)
// geometry.faces.push(faces)
const bufferGeometry=new BufferGeometry()
const count=50;
const positionsArray=new Float32Array(count*3*3);
for(let i=0;i<count*3*3;i++){
positionsArray[i]=Math.random()
}
const positionsAttribute=new THREE.BufferAttribute(positionsArray,3)
bufferGeometry.setAttribute('position',positionsAttribute)
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height);
camera.position.z = 3;
const mesh = new THREE.Mesh(bufferGeometry, material);
scene.add(mesh);
scene.add(camera);
const canvas = document.querySelector("canvas.webgl");
const renderer = new THREE.WebGLRenderer({
canvas,
});
renderer.setSize(sizes.width, sizes.height);
const controls =new OrbitControls( camera, canvas );
controls.enableDamping=true
window.addEventListener('resize',function(event){
sizes.width=window.innerWidth;
sizes.height=window.innerHeight;
camera.aspect=sizes.width/sizes.height;
camera.updateProjectionMatrix()
renderer.setSize(sizes.width,sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio,2));
})
window.addEventListener('dblclick',function(){
const fullscreenElement=document.fullscreen || document.mozFullScreen || document.webkitIsFullScreen ||document.webkitFullScreen|| document.msFullScreen
if(!fullscreenElement){
if (canvas.RequestFullScreen) {
canvas.RequestFullScreen()
//兼容Firefox
} else if (canvas.mozRequestFullScreen) {
canvas.mozRequestFullScreen()
//兼容Chrome, Safari and Opera等
} else if (canvas.webkitRequestFullScreen) {
canvas.webkitRequestFullScreen()
//兼容IE/Edge
} else if (canvas.msRequestFullscreen) {
canvas.msRequestFullscreen()
}
}else{
console.log('取消')
if(document.exitFullScreen) {
document.exitFullScreen();
//兼容Firefox
} else if(document.mozCancelFullScreen) {
document.mozCancelFullScreen();
//兼容Chrome, Safari and Opera等
} else if(document.webkitExitFullscreen) {
document.webkitExitFullscreen();
//兼容IE/Edge
} else if(element.msExitFullscreen) {
element.msExitFullscreen();
}
}
})
// gsap.to(mesh.rotation,{duration:1,delay:1,y:2})
const tick=()=>{
controls.update();
renderer.render(scene, camera);
window.requestAnimationFrame(tick)
}
tick()