运行结果
完整代码,复制到页面可用
< ! --THREEJS组件-->
< template>
< div id = "d3Container" v-loading= "loading" ref = "mainContent" >
< /div>
< /template>
< script>
import * as THREE from 'three'
import { OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js'
import { PLYLoader} from 'three/examples/jsm/loaders/PLYLoader.js'
import { PCDLoader} from 'three/examples/jsm/loaders/PCDLoader'
import { OBJLoader} from 'three/examples/jsm/loaders/OBJLoader'
import { STLLoader} from 'three/examples/jsm/loaders/STLLoader'
import { GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader" ;
export default {
name: "ThreePage" ,
props: {
/*模型资源地址*/
ossPath: {
type: String,
default ( ) {
return ''
}
} ,
/*文件类型*/
suffix: {
type: String,
default ( ) {
return 'gltf'
}
} ,
AutoFresh: {
type: Boolean,
default ( ) {
return true
}
} ,
/*是否开启自动旋转*/
autoAnimate: {
type: Boolean,
default ( ) {
return true
}
} ,
/*当前模型的颜色*/
currentColor: {
type: String,
default ( ) {
return ''
}
} ,
/*配准后的颜色*/
matchedColor: {
type: String,
default ( ) {
return ''
}
} ,
/*配准后的地址*/
matchedOssPatch: {
type: String,
default ( ) {
return ''
}
} ,
showMatchWatch: {
type: Boolean,
default ( ) {
return false
}
}
} ,
data ( ) {
return {
loading: false,
publicPath: process.env.BASE_URL,
mesh: null,
camera: null,
scene: null,
originX: 20 ,
originY: 0 ,
originZ: 20 ,
renderer: null,
controls: null,
}
} ,
mounted ( ) {
this.init( )
} ,
watch: {
//监听地址变化时需要更新地址,防止多次点击同一个渲染多次;
ossPath( val, oldVal) {
if ( val != oldVal) {
this.init( )
}
} ,
//监测是否更新整个场景
AutoFresh( val, oldVal) {
if ( val) {
this.init( )
} else {
//自我清理
this.destroyed( ) ;
}
} ,
//监测是否展示配准,更新场景,该属性的变化只负责更新场景,具体业务交给按钮的最终展现结果,按钮勾中就展示配准,没有勾中就不展示配准,属性没变就是原来的状态。
showMatchWatch( val, oldVal) {
this.init( )
} ,
//由于上传标签时,CAD会绕过。
currentColor( val, oldVal) {
if ( val != oldVal) {
this.init( )
}
}
} ,
//组件被销毁时,干掉所有3D资源;
methods: {
destroyed ( ) {
this.clear( ) ;
} ,
// 初始化
init ( ) {
/*利用vue单项数据流的特性做最后的守卫,在最底层监听是否需要展示配准图,只影响该组件的内部数据而不影响外部的matchedOssPatch*/
if ( ! this.showMatchWatch) {
this.matchedOssPatch = ''
}
this.createScene( ) // 创建场景
this.loadLoader( ) // 加载P模型
this.createLight( ) // 创建光源
this.createCamera( ) // 创建相机
this.createRender( ) // 创建渲染器
this.createControls( ) // 创建控件对象
this.render( ) // 渲染
} ,
//清除当前所有场景
clear ( ) {
this.mesh = null
this.camera = null
this.scene = null
this.renderer = null
this.controls = null
cancelAnimationFrame( this.animationId)
console.log( "我要清除啦" ) ;
} ,
// 创建场景
createScene ( ) {
this.loading = true ;
this.scene = new THREE.Scene( )
var grid = new THREE.GridHelper( 24 , 24 , 0xFF0000, 0x444444) ;
grid.material.opacity = 0.4 ;
grid.material.transparent = true ;
grid.rotation.x = Math.PI / 2.0 ;
this.scene.add( grid)
} ,
// 加载PLY模型
loadLoader ( ) {
const THIS = this
// const loader = this.mapLoader( ) ;
let loader = new GLTFLoader( ) ;
loader.load( window.location.origin + ` /fs/files/download/6128764fac0ba25313e73b4d` , geometry = > {
// loader.load( THIS.ossPath, geometry = > {
// geometry.center( ) ;
this.loading = false ;
let material = null;
// this.isLoading = false ; //关闭载入中效果
this.mesh = geometry.scene;
this.mesh.scale.set( 0.4 , 0.4 , 0.4 ) ; //设置大小比例
this.mesh.position.set( 0 , 0 , 0 ) ; //设置位置
this.scene.add( this.mesh) ; // 将模型引入three、
// this.animate( ) ;
} )
//如果有配准结果,加载配准结果,配准结果未ply格式;
} ,
// 创建光源
createLight ( ) {
// 环境光
let pointColor = '#ffffff' ;
const ambientLight = new THREE.AmbientLight( 0x222222, 0.35 ) // 创建环境光
this.scene.add( ambientLight) // 将环境光添加到场景
const spotLight = new THREE.SpotLight( 0xffffff) // 创建聚光灯
spotLight.position.set( 50 , 50 , 50 )
spotLight.castShadow = true ; //平行光开启阴影
spotLight.receiveShadow = true ;
this.scene.add( spotLight)
} ,
// 创建相机
createCamera ( ) {
const element = this.$refs .mainContent
const width = element.clientWidth // 窗口宽度
const height = element.clientHeight //
this.cWidth = width;
this.cHeight = height;
const k = width / height // 窗口宽高比
this.aspect = k;
// PerspectiveCamera( fov, aspect, near, far )
this.camera = new THREE.PerspectiveCamera( 35 , k, 1 , 10000 )
this.camera.position.set( this.originX, this.originY, this.originZ) // 设置相机位置
this.camera.up.set( 0 , 0 , 1 ) ;
this.camera.lookAt( new THREE.Vector3( this.originX, this.originY, this.originZ)) // 设置相机方向
this.scene.add( this.camera)
} ,
// 创建渲染器
createRender ( ) {
const element = this.$refs .mainContent
this.renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true, preserveDrawingBuffer: true} )
this.renderer.setSize( element.clientWidth, element.clientHeight) // 设置渲染区域尺寸
this.renderer.shadowMap.enabled = true // 显示阴影
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap
this.renderer.setClearColor( new THREE.Color( 0xEEEEEE)) // 设置背景颜色
// this.renderer.setClearColor( new THREE.Color( 0x111111)) // 设置背景颜色
element.innerHTML = '' ;
element.appendChild( this.renderer.domElement)
} ,
render ( ) {
this.animationId = requestAnimationFrame( this.render) ; //旋转动画;
this.renderer.render( this.scene, this.camera)
this.controls.update( ) ;
} ,
// 创建控件对象
createControls ( ) {
this.controls = new OrbitControls( this.camera, this.renderer.domElement)
} ,
onWindowResize ( ) {
this.camera.aspect = this.aspect;
this.camera.updateProjectionMatrix( ) ;
}
}
}
< /script>
< style scoped>
width: 100 %;
height: 100 %;
z-index: 888 ;
}
< /style>