在通过Three.js实现一个基础渲染代码中,我对代码做了调整,让其可以随着div窗口大小进行适配调整。
安装依赖
pnpm i three
版本选择
"three": "^0.154.0",
实例演示地址
手动指定宽高
今天我们来指定一个固定宽高来看看效果。
这里我们使用renderer.setSize来设置画布的大小,我们也可以通过js获取div宽和高,然后设置画布的大小。这里我推荐获取div宽高来设置画布大小。
renderer.setSize(300,200);
除了画布的大小,我们还需要考虑相机,要和画布大小或者说宽高比保持一致,如果不一致会怎么样呢?渲染器渲染出来的内容就会变形。
// 创建相机
const aspect = 300 / 200;
const camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000);
camera.position.set(100, 100, 100);
camera.lookAt(scene.position);
动态获取div宽和高
<div class="rendererDom" ref="rendererDom"/>
// 设置初始尺寸
renderer.setSize(rendererDom.value.clientWidth, rendererDom.value.clientHeight);
rendererDom.value.appendChild(renderer.domElement);
// 创建一个 ResizeObserver 实例并监听 rendererDom 的尺寸变化
const resizeObserver = new ResizeObserver(entries => {
// 更新渲染器的尺寸
for (let entry of entries) {
renderer.setSize(entry.contentRect.width, entry.contentRect.height);
camera.aspect = entry.contentRect.width / entry.contentRect.height;
camera.updateProjectionMatrix();
}
});
resizeObserver.observe(rendererDom.value);
onUnmounted(() => {
// 停止监听
resizeObserver.unobserve(rendererDom.value);
});
完整实例代码
<template>
<!-- 定义一个用于承载Three.js渲染结果的div元素 -->
<div class="rendererDom" ref="rendererDom"/>
</template>
<script>
import {onMounted, onUnmounted, ref} from 'vue';
import * as THREE from 'three';
export default {
setup() {
const rendererDom = ref(null);
onMounted(() => {
// 创建场景
const scene = new THREE.Scene();
// 创建立方体
const geometry = new THREE.BoxGeometry(50, 50, 50);
const material = new THREE.MeshLambertMaterial({
color: 0x003afe
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// 创建光源
const point = new THREE.PointLight(0xffffff, 1, 0);
point.position.set(50, 50, 100);
scene.add(point);
// 创建点光源辅助器,并添加到场景
const pointLightHelper = new THREE.PointLightHelper(point);
scene.add(pointLightHelper);
const ambient = new THREE.AmbientLight(0x444444, 1);
scene.add(ambient);
// 创建相机
const aspect = rendererDom.value.clientWidth / rendererDom.value.clientHeight;
const camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000);
camera.position.set(100, 100, 100);
camera.lookAt(scene.position);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(rendererDom.value.clientWidth, rendererDom.value.clientHeight);
renderer.setClearColor(0xb9d3ff, 1);
rendererDom.value.appendChild(renderer.domElement);
// 渲染
const animate = function () {
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
animate();
// 创建一个 ResizeObserver 实例并监听 rendererDom 的尺寸变化
const resizeObserver = new ResizeObserver(entries => {
for (let entry of entries) {
renderer.setSize(entry.contentRect.width, entry.contentRect.height);
camera.aspect = entry.contentRect.width / entry.contentRect.height;
camera.updateProjectionMatrix();
}
});
resizeObserver.observe(rendererDom.value);
onUnmounted(() => {
if (rendererDom.value instanceof Element) {
resizeObserver.unobserve(rendererDom.value);
}
rendererDom.value = null;
});
});
return {rendererDom};
},
};
</script>
<style lang="scss">
.rendererDom {
width: 300px;
height: 200px;
position: fixed;
}
</style>
视频教程地址
今天学习视频教程 《WebGL/Three.js前端高薪3D可视化》-大屏3D地图可视化-threejs 渲染非全屏(相机和渲染器)
实例代码下载
当前学习笔记演示实例代码
项目运行环境 vue3 vite js nodejs 14