*案例42 创建一个透明的立方体
html
复制代码
<template>
<div ref="container" className="container"></div>
</template>
<script setup>
import * as THREE from 'three';
import WebGL from 'three/examples/jsm/capabilities/WebGL.js'
// 引入轨道控制器扩展库OrbitControls.js
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js'
import {TransformControls} from 'three/examples/jsm/controls/TransformControls.js'
import { CSS3DRenderer, CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';
import { RectAreaLightHelper } from 'three/examples/jsm/helpers/RectAreaLightHelper.js';
import { RectAreaLightUniformsLib } from 'three/examples/jsm/lights/RectAreaLightUniformsLib.js';
import {ref, onMounted} from 'vue'
let container = ref(null)
onMounted(() => {
/*
* * 创建场景(渲染必加代码)
*/
// 获取容器的实际宽高
const containerWidth = container.value.clientWidth;
const containerHeight = container.value.clientHeight;
// 创建场景
const scene = new THREE.Scene();
/*
* * 创建摄像机(渲染必加代码)
* */
// 创建摄像机(three.js有好几种摄像机,这里用的是透视摄像机)
// 参数 1:fov视野角度(注意:这个参数如果调整不好,会导致物体的透视效果看起来怪怪的)
// 控制相机能看到的角度范围。
// 就像你眼睛睁得越大,看到的范围就越广;睁得越小,看到的范围就越窄
// 参数 2:aspect长宽比,控制相机看到的画面的宽高比。
// 就像你调整手机屏幕的横屏或竖屏模式,画面的宽高比会变化
// 参数 3:near近截面,控制相机能看到的最小距离,默认值是0.1
// 1 表示距离相机 1 个单位以内的物体不会被渲染
// 参数 4:far远截面,控制相机能看到的最大距离
// 1000 表示距离相机 1000 个单位以外的物体不会被渲染
const camera = new THREE.PerspectiveCamera(30, containerWidth / containerHeight, 1, 100);
// camera.position 和 camera.lookAt 如果不设置可能会导致画面看不到效果
// 摄像机的位置
camera.position.set(5, 3.5, 4.7);
// 摄像机聚焦的位置
camera.lookAt(0, 0, 0);
// zoom属性可以获取或者设置摄像机的缩放倍数,其默认值为1
camera.zoom = 1
// 【注意,在大多数属性发生改变之后,需要调用.updateProjectionMatrix来使得这些改变生效】
camera.updateProjectionMatrix()
/*
* * 创建渲染器(渲染必加代码)
* */
// 创建渲染器(three.js有好几种渲染器)
const renderer = new THREE.WebGLRenderer();
// 设置渲染器尺寸
// 第三个参数(选填):false代表以较低分辨率渲染
renderer.setSize(containerWidth, containerHeight );
// 将渲染器放入文档中
container.value.appendChild(renderer.domElement);
/*
* 创建坐标轴对象(用于辅助创建3D场景)
* */
// AxesHelper() 的参数代表坐标轴的线段长度
// 红色代表x轴,绿色代表y轴,蓝色代表z轴
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
/*
* 创建轨道控制器
* */
const orbitControls = new OrbitControls(camera, renderer.domElement);
// 更新控制器
orbitControls.update();
orbitControls.addEventListener('change', function () {
// 输出相机位置
//console.log('camera.position', camera.position);
});
/*
* 创建一个透明的立方体
* (效果不太理想,立方体的背面没有显示)
* */
// 新建立方体对象
const geometry = new THREE.BoxGeometry(1,1,1);
// 创建材质
// MeshBasicMaterial材质不受光照影响
const material = new THREE.MeshBasicMaterial({
// 材质颜色
color: '#2ccdf1',
// 启用透明
transparent: true,
// 设置透明度
opacity: 0.35,
// 渲染正面和背面
side: THREE.DoubleSide,
});
// 新建网格(网格包含集合体和作用在几何体上面的材质)
const cube = new THREE.Mesh(geometry, material);
// 将网格添加到场景
scene.add(cube);
/*
* 渲染场景必加代码 (渲染循环)
* */
// 渲染循环
function animate() {
// 每秒执行60次
requestAnimationFrame(animate);
// 更新控制器
orbitControls.update();
// 渲染场景
renderer.render(scene, camera);
}
// WebGL兼容性检查
if (WebGL.isWebGLAvailable()) {
animate();
} else {
const warning = WebGL.getWebGLErrorMessage();
container.value.appendChild(warning);
}
/**
* 窗口变化自适应(必加代码)
*/
const onWindowResize = () => {
// 获取容器的实际宽高
const containerWidth = container.value.clientWidth;
const containerHeight = container.value.clientHeight;
// 重置渲染器输出画布canvas尺寸
renderer.setSize(containerWidth, containerHeight);
// aspect属性 是摄像机视锥体的长宽比,通常设置为,画布的宽/画布的高
// 全屏情况下:设置 观察范围长宽比aspect,为窗口宽高比
camera.aspect =containerWidth / containerHeight;
// 渲染器执行render方法的时候会读取相机对象的投影矩阵属性projectionMatrix
// 但是不会每渲染一帧,就通过相机的属性计算投影矩阵(节约计算资源)
// 因此如果相机的属性发生了变化,需要执行updateProjectionMatrix ()方法来使得这些属性生效
camera.updateProjectionMatrix();
}
// 监听浏览器窗口大小改变
window.addEventListener('resize', onWindowResize);
})
</script>
<style>
</style>
<style scoped>
.container {
height: 100vh;
box-sizing: border-box;
/* overflow属性(必填),否则页面自适应时,偶尔会出现滚动条*/
overflow: hidden;
}
</style>
*案例43 创建一个线框球体
html
复制代码
<template>
<div ref="container" className="container"></div>
</template>
<script setup>
import * as THREE from 'three';
import WebGL from 'three/examples/jsm/capabilities/WebGL.js'
// 引入轨道控制器扩展库OrbitControls.js
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js'
import {TransformControls} from 'three/examples/jsm/controls/TransformControls.js'
import { CSS3DRenderer, CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';
import { RectAreaLightHelper } from 'three/examples/jsm/helpers/RectAreaLightHelper.js';
import { RectAreaLightUniformsLib } from 'three/examples/jsm/lights/RectAreaLightUniformsLib.js';
import {ref, onMounted} from 'vue'
let container = ref(null)
onMounted(() => {
/*
* * 创建场景(渲染必加代码)
*/
// 获取容器的实际宽高
const containerWidth = container.value.clientWidth;
const containerHeight = container.value.clientHeight;
// 创建场景
const scene = new THREE.Scene();
/*
* * 创建摄像机(渲染必加代码)
* */
// 创建摄像机(three.js有好几种摄像机,这里用的是透视摄像机)
// 参数 1:fov视野角度(注意:这个参数如果调整不好,会导致物体的透视效果看起来怪怪的)
// 控制相机能看到的角度范围。
// 就像你眼睛睁得越大,看到的范围就越广;睁得越小,看到的范围就越窄
// 参数 2:aspect长宽比,控制相机看到的画面的宽高比。
// 就像你调整手机屏幕的横屏或竖屏模式,画面的宽高比会变化
// 参数 3:near近截面,控制相机能看到的最小距离,默认值是0.1
// 1 表示距离相机 1 个单位以内的物体不会被渲染
// 参数 4:far远截面,控制相机能看到的最大距离
// 1000 表示距离相机 1000 个单位以外的物体不会被渲染
const camera = new THREE.PerspectiveCamera(30, containerWidth / containerHeight, 1, 100);
// camera.position 和 camera.lookAt 如果不设置可能会导致画面看不到效果
// 摄像机的位置
camera.position.set(5, 3.5, 4.7);
// 摄像机聚焦的位置
camera.lookAt(0, 0, 0);
// zoom属性可以获取或者设置摄像机的缩放倍数,其默认值为1
camera.zoom = 1
// 【注意,在大多数属性发生改变之后,需要调用.updateProjectionMatrix来使得这些改变生效】
camera.updateProjectionMatrix()
/*
* * 创建渲染器(渲染必加代码)
* */
// 创建渲染器(three.js有好几种渲染器)
const renderer = new THREE.WebGLRenderer();
// 设置渲染器尺寸
// 第三个参数(选填):false代表以较低分辨率渲染
renderer.setSize(containerWidth, containerHeight );
// 将渲染器放入文档中
container.value.appendChild(renderer.domElement);
/*
* 创建坐标轴对象(用于辅助创建3D场景)
* */
// AxesHelper() 的参数代表坐标轴的线段长度
// 红色代表x轴,绿色代表y轴,蓝色代表z轴
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
/*
* 创建轨道控制器
* */
const orbitControls = new OrbitControls(camera, renderer.domElement);
// 更新控制器
orbitControls.update();
orbitControls.addEventListener('change', function () {
// 输出相机位置
//console.log('camera.position', camera.position);
});
/*
* 创建一个线框球体
* */
// 新建球体
const geometry = new THREE.SphereGeometry( 1, 16, 16 );
// 创建材质
// MeshBasicMaterial材质不受光照影响
const material = new THREE.MeshBasicMaterial({
// 材质颜色
color: '#2ccdf1',
// 将几何体渲染为线框。默认值为false(即渲染为平面多边形)
wireframe: true,
// 控制线框宽度(chrome上不好使)
wireframeLinewidth: 5,
// 定义线连接节点的样式。可选值为 'round', 'bevel' 和 'miter'。默认值为 'round'
wireframeLinejoin: 'round',
});
// 新建网格(网格包含集合体和作用在几何体上面的材质)
const cube = new THREE.Mesh(geometry, material);
// 将网格添加到场景
scene.add(cube);
/*
* 渲染场景必加代码 (渲染循环)
* */
// 渲染循环
function animate() {
// 每秒执行60次
requestAnimationFrame(animate);
// 更新控制器
orbitControls.update();
// 渲染场景
renderer.render(scene, camera);
}
// WebGL兼容性检查
if (WebGL.isWebGLAvailable()) {
animate();
} else {
const warning = WebGL.getWebGLErrorMessage();
container.value.appendChild(warning);
}
/**
* 窗口变化自适应(必加代码)
*/
const onWindowResize = () => {
// 获取容器的实际宽高
const containerWidth = container.value.clientWidth;
const containerHeight = container.value.clientHeight;
// 重置渲染器输出画布canvas尺寸
renderer.setSize(containerWidth, containerHeight);
// aspect属性 是摄像机视锥体的长宽比,通常设置为,画布的宽/画布的高
// 全屏情况下:设置 观察范围长宽比aspect,为窗口宽高比
camera.aspect =containerWidth / containerHeight;
// 渲染器执行render方法的时候会读取相机对象的投影矩阵属性projectionMatrix
// 但是不会每渲染一帧,就通过相机的属性计算投影矩阵(节约计算资源)
// 因此如果相机的属性发生了变化,需要执行updateProjectionMatrix ()方法来使得这些属性生效
camera.updateProjectionMatrix();
}
// 监听浏览器窗口大小改变
window.addEventListener('resize', onWindowResize);
})
</script>
<style>
</style>
<style scoped>
.container {
height: 100vh;
box-sizing: border-box;
/* overflow属性(必填),否则页面自适应时,偶尔会出现滚动条*/
overflow: hidden;
}
</style>