three.js+vue3+vite教学(四、监控性能,交互控制)

监控性能

我们在看three官网的时候总能看到这样的东西
在这里插入图片描述

这其实是在监控我们的浏览器性能

那么,怎么去实现呢

安装依赖

yarn add stats.js
yarn add @types/stats.js -D

在这里插入图片描述
我们可以看到有fps,ms等等

引入

在这里插入图片描述

实时更新

在这里插入图片描述

通过ref拿到组件

在这里插入图片描述

渲染dom结构

在这里插入图片描述
在这里插入图片描述
代码

<template>
  <div ref="statsRef"></div>
  <div class="contain" ref="containerRef">
  </div>
</template>

<script setup lang='ts'>
import { AxesHelper, BoxGeometry, Color, Mesh, MeshBasicMaterial, MeshLambertMaterial, PerspectiveCamera, PlaneGeometry, Scene, SphereGeometry, SpotLight, WebGLRenderer } from 'three';
import { ref, reactive, onMounted } from 'vue'
import Stats from 'stats.js'
const containerRef = ref<HTMLDivElement>()
const statsRef = ref<HTMLDivElement>()
const stats = new Stats()
stats.dom.style.top = "50px"
stats.showPanel(0)
// 创建场景
const scene = new Scene()
// 创建照相机
const camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000)
// 设置摄像机位置
camera.position.set(-30, 40, 30)
// 设置摄像机朝向(看哪)
camera.lookAt(scene.position)
// webgl渲染器
const renderer = new WebGLRenderer()
renderer.setClearColor(new Color(0xeeeeee))
renderer.setSize(window.innerWidth, window.innerHeight)
// 可以渲染阴影
renderer.shadowMap.enabled = true

// 光源
const spotLight = new SpotLight(0xffffff)
spotLight.castShadow = true
spotLight.position.set(-40, 60, -10)
scene.add(spotLight)

// 添加平面几何体
const planeGeometry = new PlaneGeometry(60, 20)
// 添加材质
const meshBasicMaterial = new MeshLambertMaterial({ color: 0xcccccc })
const plane = new Mesh(planeGeometry, meshBasicMaterial)
// 接受阴影
plane.receiveShadow = true
// 调整位置
plane.rotation.x = -0.5 * Math.PI //放平
plane.position.x = 15
plane.position.y = 0
plane.position.z = 0
scene.add(plane)

// 添加几何体
const cubeGeometry = new BoxGeometry(4, 4, 4)
const cubeMaterial = new MeshLambertMaterial({ color: 0xff0000, wireframe: false })
const cube = new Mesh(cubeGeometry, cubeMaterial)
cube.castShadow = true
cube.position.set(2, 2, 2)
scene.add(cube)

// 球体
const sphereGeometry = new SphereGeometry(4)
const sphereMaterial = new MeshLambertMaterial({ color: 0x7777ff, wireframe: false })
const sphere = new Mesh(sphereGeometry, sphereMaterial)
sphere.castShadow = true
sphere.position.x = 20
sphere.position.y = 4
sphere.position.z = 2
scene.add(sphere)
// 添加坐标系
const axes = new AxesHelper(20)
scene.add(axes)

let step = 0
function renderScene(){
  stats.update()
  cube.rotation.x += 0.02
  cube.rotation.y += 0.02
  cube.rotation.z += 0.02

  step += 0.04
  sphere.position.x = 20+10*Math.cos(step)
  sphere.position.y = 2*10*Math.abs(Math.sin(step))

  requestAnimationFrame(renderScene)
  renderer.render(scene,camera)
}
renderScene()
onMounted(() => {
  statsRef.value?.append(stats.dom)
  containerRef.value?.appendChild(renderer.domElement)
  renderer.render(scene, camera)
})
</script>

<style scoped>

</style>

交互控制

交互控制是指这些东西
在这里插入图片描述

我们可以配置几何体运动速率啊,大小啊,添加几何体。。。等等

安装依赖

yarn add dat.gui

yarn add @types/dat.gui -D

引入
在这里插入图片描述

实例化

在这里插入图片描述
效果
在这里插入图片描述

我们加上我们想要控制的项

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这样就可以控制了
但是现在有一个问题,这个面板会重复地渲染,导致存在多个,就是我们每次刷新都会重新渲染

所以我们解决一下
在这里插入图片描述

代码

<template>
  <div ref="statsRef"></div>
  <div className="contain" ref="containerRef">
  </div>
</template>

<script setup lang='ts'>
import {
  AxesHelper,
  BoxGeometry,
  Color,
  Mesh,
  MeshBasicMaterial,
  MeshLambertMaterial,
  PerspectiveCamera,
  PlaneGeometry,
  Scene,
  SphereGeometry,
  SpotLight,
  WebGLRenderer
} from 'three';
import { ref, reactive, onMounted } from 'vue'
import Stats from 'stats.js'
import * as dat from 'dat.gui'

const containerRef = ref<HTMLDivElement>()
const statsRef = ref<HTMLDivElement>()
const stats = new Stats()
stats.dom.style.top = "50px"
stats.showPanel(0)
// 创建场景
const scene = new Scene()
// 创建照相机
const camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000)
// 设置摄像机位置
camera.position.set(-30, 40, 30)
// 设置摄像机朝向(看哪)
camera.lookAt(scene.position)
// webgl渲染器
const renderer = new WebGLRenderer()
renderer.setClearColor(new Color(0xeeeeee))
renderer.setSize(window.innerWidth, window.innerHeight)
// 可以渲染阴影
renderer.shadowMap.enabled = true

// 光源
const spotLight = new SpotLight(0xffffff)
spotLight.castShadow = true
spotLight.position.set(-40, 60, -10)
scene.add(spotLight)

// 添加平面几何体
const planeGeometry = new PlaneGeometry(60, 20)
// 添加材质
const meshBasicMaterial = new MeshLambertMaterial({ color: 0xcccccc })
const plane = new Mesh(planeGeometry, meshBasicMaterial)
// 接受阴影
plane.receiveShadow = true
// 调整位置
plane.rotation.x = -0.5 * Math.PI //放平
plane.position.x = 15
plane.position.y = 0
plane.position.z = 0
scene.add(plane)

// 添加几何体
const cubeGeometry = new BoxGeometry(4, 4, 4)
const cubeMaterial = new MeshLambertMaterial({ color: 0xff0000, wireframe: false })
const cube = new Mesh(cubeGeometry, cubeMaterial)
cube.castShadow = true
cube.position.set(2, 2, 2)
scene.add(cube)

// 球体
const sphereGeometry = new SphereGeometry(4)
const sphereMaterial = new MeshLambertMaterial({ color: 0x7777ff, wireframe: false })
const sphere = new Mesh(sphereGeometry, sphereMaterial)
sphere.castShadow = true
sphere.position.x = 20
sphere.position.y = 4
sphere.position.z = 2
scene.add(sphere)
// 添加坐标系
const axes = new AxesHelper(20)
scene.add(axes)

const controlRef = ref({
  rotationSpeed: 0.02,
  bouncingSpeed: 0.03
})
// const gui = new dat.GUI()
// gui.add(controlRef.value,"rotationSpeed",0,0.5)
// gui.add(controlRef.value,"bouncingSpeed",0,0.5)
// 判斷
if (document.querySelectorAll(".dg.ac>.dg.main.a").length === 0) {
  const gui = new dat.GUI()
  gui.add(controlRef.value, "rotationSpeed", 0, 0.5)
  gui.add(controlRef.value, "bouncingSpeed", 0, 0.5)
}
let step = 0

function renderScene() {
  stats.update()
  cube.rotation.x += controlRef.value.rotationSpeed
  cube.rotation.y += controlRef.value.rotationSpeed
  cube.rotation.z += controlRef.value.rotationSpeed

  step += controlRef.value.bouncingSpeed
  sphere.position.x = 20 + 10 * Math.cos(step)
  sphere.position.y = 2 * 10 * Math.abs(Math.sin(step))

  requestAnimationFrame(renderScene)
  renderer.render(scene, camera)
}

renderScene()
onMounted(() => {
  statsRef.value?.append(stats.dom)
  containerRef.value?.appendChild(renderer.domElement)
  renderer.render(scene, camera)
})
</script>

<style scoped>

</style>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林多多@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值