Vue3中threejs模型缩略图生成的简单实现

目录

一、前言

二、简介

三、简单实现

0、准备

1、创建场景

2.模型导入

3.生成Base64

4.绑定图片

四、结果展示


一、前言

        三维模型由于其需要将模型的每个面与边进行渲染,往往会出现打开模型十分缓慢的问题。那么这问题该如何解决呢,最简单粗暴的方法当然是对模型载入不断的进行优化,但是优化往往是最困难的。从另一方面想,让用户精准的打开自己需要的模型,是不是也能一定程度的缓解该问题呢?所以实现三维模型的缩略图是很有必要的。

二、简介

        本文实现模型缩略图主要的框架为Vue3,使用threejs来管理模型。总的分为三步:1.准备threejs场景容器;2.构建threjs场景,载入模型;3.canvas转base64编码,将其载入img容器中。

三、简单实现

0、准备

        首先,既然要导入模型,就需要准备一个想要添加到场景中的模型。在此推荐一个模型下载网站SketChfab,Threejs源码中引用模型大多出自于此。

        然后,需要给生成的canvas准备一个容器:

<template>
    <div id="thumbnail"></div>
</template>

        创建一个ts文件,整合模型场景能用到的操作,在此将其命名为sceneCreator:

1、创建场景

基本的场景创建不再赘述,不理解的可以参考Vue3中简单使用Three.js

//引入threejs
import * as THREE from 'three' 
//引入加载器
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
​
class SceneCreator {
   public scene: THREE.Scene = new THREE.Scene()
   private camera: THREE.PerspectiveCamera
   private renderer: THREE.Renderer
   private controls: OrbitControls
​
   constructor (fatherElement: HTMLElement) {
     this.scene.background = new THREE.Color(0xaaaaaa)
     // 添加光源
     this.initLight()
​
     // 创建一个透视相机
     const width = window.innerWidth; const height = window.innerHeight
     this.camera = new THREE.PerspectiveCamera(45, width / height, 1, 5000)
     // 设置相机位置
     this.camera.position.set(100, 400, 600)
     // 设置相机方向
     this.camera.lookAt(0, 0, 0)
​
     // 创建辅助坐标轴
     const axesHelper = new THREE.AxesHelper(100)
     this.scene.add(axesHelper)
​
     // 创建一个WebGL渲染器
     this.renderer = new THREE.WebGLRenderer()
     this.renderer.setSize(width, height)
     this.renderer.render(this.scene, this.camera)
​
     fatherElement.appendChild(this.renderer.domElement)
   }
​
   render () {
     this.renderer.render(this.scene, this.camera)
   }
    /**
    *灯光初始化
    */
   initLight () {
     const ambient = new THREE.AmbientLight(0x505050)
     this.scene.add(ambient)
     const pointLight1 = new THREE.PointLight(0xffffff, 0.4)
     const pointLight2 = new THREE.PointLight(0xffffff, 0.4)
     pointLight1.position.set(200, 300, 400)
     this.scene.add(pointLight1)
     pointLight2.position.set(-200, -300, -400)
     this.scene.add(pointLight2)
​
     const hemiLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.6)
     hemiLight.color.setHSL(0.6, 1, 0.6)
     hemiLight.groundColor.setHSL(0.095, 1, 0.75)
     hemiLight.position.set(0, 200, 0)
     this.scene.add(hemiLight)
​
     const hemiLightHelper = new THREE.HemisphereLightHelper(hemiLight, 10)
     this.scene.add(hemiLightHelper)
​
     const dirLight = new THREE.DirectionalLight(0xffffff, 1)
     dirLight.color.setHSL(0.1, 1, 0.95)
     dirLight.position.set(-100, 175, 100)
     dirLight.position.multiplyScalar(30)
     this.scene.add(dirLight)
   }
}
//暴露
export { SceneCreator }

2.模型导入

        在此,使用threejs中的GLTFLoader来加载下载好的glb,由于制作缩略图并不需要对模型进行什么特殊操作,所以只需要将加载好的模型添加进场景即可。

createCar () {
     const loader = new GLTFLoader()
​
     const glbHref = new URL('../assets/glb/car/ferrari_458.glb', import.meta.url).href
​
     loader.load(glbHref, (gltf) => {
       const carModel = gltf.scene.children[0]
​
       this.scene.add(carModel)
     })
   }

3.生成Base64

<script lang='ts' setup>
import { onMounted, Ref, ref } from 'vue'
import { SceneCreator } from '../utils/sceneCreator'
​
let myScene: SceneCreator
const img:Ref<string> = ref('')
​
const createThumbnails = async () => {
  const el = document.getElementById('thumbnail')
  if (el) {
    // 创建场景
    myScene = new SceneCreator(el)
    // 场景自适应,防止模型变形
    myScene.resize()
    // 载入模型,由于loader是异步的所以我们需要等它加载好后再生成base64,否则生成的图片是没有模型的
    await myScene.createCar()
    myScene.render()
    // 生成base64
    const canvas = el.children[0] as HTMLCanvasElement
    img.value = canvas.toDataURL('img/png')
    // 不需要展示canvas就移除它
    // el.remove()
  }
}
​
onMounted(() => {
  createThumbnails()
})
</script>

4.绑定图片

        创建img标签,将第3步中生成的base64绑定到img标签的scr中即可。

<template>
  <div id="thumbnail"></div>
  <img :src="img" alt="">
</template>

四、结果展示

猜你喜欢

转载自blog.csdn.net/qq_52013792/article/details/128129616