three.js教程创建仓库场景示例一

首先创建一个空间场景,Template等配置文件可参考three.js教程学习初始化配置

director.js 

import Template from "../common/Template"
import * as THREE from 'three'
import House from "../objects/House"
export default class Director extends Template{
  constructor (ele) {
    super()
    this.ele = ele
    this.PCamera.fov = 45
    this.PCamera.far = 10000
    this.PCamera.near = 1
    this.rendererColor = new THREE.Color(0x01031c)
    this.cameraPostion = new THREE.Vector3(150, 100, 0)

    this.init(this.ele)
    this.addLight() 
    this.addAxesHelper(1000)
    if(this.camera && this.renderer) this.addOrbitControls(this.camera, this.renderer.domElement);
    this.animate()
    this.addGround()
  }
  addGround(){
    const groundGeometry = new THREE.PlaneGeometry(150,250)
    const groundMaterial = new THREE.MeshLambertMaterial({
      color:0x454942
    })

    let ground = new THREE.Mesh(groundGeometry, groundMaterial)
    ground.rotation.x = -Math.PI/2
    ground.name = '地'
    this.scene.add(ground)
    this.meshList.push(ground)
  }
  addLight(){
    this.addAmbientLight(0x666666)
    this.addDirectionalLight(0xdfebff,{x:50, y:200, z:100},1)
  }
  animate () {
    // 执行运动动画
    if(this.renderer && this.camera){
      this.renderer.render(this.scene, this.camera)
      requestAnimationFrame(this.animate.bind(this))
    }
  }
}

在object中创建House.js文件夹,新增房子,拆开看就是shape+hole四面墙、窗户、门

 house.js代码如下

import {DoubleSide, Group,BoxGeometry,
  MeshPhysicalMaterial,
  Shape,
  MeshLambertMaterial,
  Mesh,
  Path,
  ExtrudeGeometry,BoxBufferGeometry} from 'three'
import * as THREE from 'three'
import Base from "../common/Base"
import {Box} from "./Model"

export default class House extends Base{
  constructor (length,width,height,scene) {
    super()
    this.length = length
    this.width = width
    this.height = height
    this.scene = scene
    this.instance = new Group()
    // 实体
    this.addFloor()       // 地面PlaneGeometry
    this.addWall()        // 四壁墙Shape
    this.addAllWindow()   // 窗户
    this.addDoor()        // 门Group
  }
  addAllWindow(){
    this.window1 = this.addWindow('窗户1')      // 前左
    this.window1.position.set(this.width/2,this.height/3,this.length/4)
    this.window1.rotation.y = Math.PI/2

    this.window2 = this.addWindow('窗户2')      // 前右
    this.window2.position.set(this.width/2,this.height/3,-this.length/4)
    this.window2.rotation.y = Math.PI/2

    // this.window3 = this.addWindow('窗户3')      // 后左
    // this.window3.position.set(-this.width/2,this.height/3,this.length/4)
    // this.window3.rotation.y = Math.PI/2

    // this.window4 = this.addWindow('窗户4')      // 后右
    // this.window4.position.set(-this.width/2,this.height/3,-this.length/4)
    // this.window4.rotation.y = Math.PI/2
    
    // this.window5 = this.addWindow('窗户5')      // 左
    // this.window5.position.set(0,this.height/3,this.length/2)
    // this.window6 = this.addWindow('窗户6')      // 右
    // this.window6.position.set(0,this.height/3,-this.length/2)
  }

  addFloor () {
    const geometry = new THREE.PlaneBufferGeometry(this.width, this.length)
    const material = new THREE.MeshLambertMaterial({
      color:0x1e7047
    })

    let floor = new THREE.Mesh(geometry, material)
    floor.rotation.x = -Math.PI/2
    floor.name = '地面'
    this.instance.add( floor )
  }

  addWall () {

    let wall = new THREE.Group()

    const shape = new Shape()
    shape.moveTo(0,0)
    shape.lineTo(this.length,0)
    shape.lineTo(this.length,this.height)
    shape.lineTo(0,this.height)
    // 门
    const hole_1 = new Path()
    hole_1.moveTo(this.length/2-this.length/30,0)
    hole_1.lineTo(this.length/2+this.length/30,0)
    hole_1.lineTo(this.length/2+this.length/30,this.height-this.height/4)
    hole_1.lineTo(this.length/2-this.length/30,this.height-this.height/4)
    shape.holes.push(hole_1)
    // 窗户
    const hole_2 = new Path()
    hole_2.moveTo(this.length/4,this.height/3)
    hole_2.lineTo(this.length/4+this.length/16,this.height/3)
    hole_2.lineTo(this.length/4+this.length/16,this.height/3+this.height/2)
    hole_2.lineTo(this.length/4,this.height/3+this.height/2)
    shape.holes.push(hole_2)
    const hole_3 = new Path()
    hole_3.moveTo(this.length/4+this.length/2,this.height/3)
    hole_3.lineTo(this.length/4+this.length/16+this.length/2,this.height/3)
    hole_3.lineTo(this.length/4+this.length/16+this.length/2,this.height/3+this.height/2)
    hole_3.lineTo(this.length/4+this.length/2,this.height/3+this.height/2)
    shape.holes.push(hole_3)

  
    const extrudeSettings = { 
      depth: 0.1, 
      bevelEnabled: true, 
      bevelSegments: 2, 
      steps: 2, 
      bevelSize: 0.5, 
      bevelThickness: 0.1
    };
    // 前墙
    const geometry = new ExtrudeGeometry( shape, extrudeSettings );
    const material = new MeshLambertMaterial({ 
      color: 0xffffff,
    })
    const frontWall = new Mesh( geometry, material )
    frontWall.rotation.y = Math.PI/2
    frontWall.position.set(this.width/2,0,this.length/2)
    wall.add(frontWall)
    // 后墙
    const backgeometry = new THREE.BoxBufferGeometry( this.length,this.height,1 );
    const backWall = new Mesh( backgeometry, material )
    backWall.rotation.y = Math.PI/2
    backWall.position.set(-this.width/2,this.height/2,0)
    wall.add(backWall)

    // 左右
    const leftrightgeometry = new THREE.BoxBufferGeometry( this.width,this.height,1 );
    const leftWall = new Mesh( leftrightgeometry, material )
    leftWall.position.set(0,this.height/2,this.length/2)
    wall.add(leftWall)
    const rightWall = new Mesh( leftrightgeometry, material )
    rightWall.position.set(0,this.height/2,-this.length/2)
    wall.add(rightWall)

    this.instance.add(wall)
  }

  addWindow (name) {
    let window = new Group()
    let w = this.length/16
    let h = this.height/2
    
    // 窗户边框
    const shape = new Shape()
    shape.moveTo(0,0)
    shape.lineTo(w,0)
    shape.lineTo(w,h)
    shape.lineTo(0,h)
  
    const hole_1 = new Path()
    hole_1.moveTo(w/100,h/100)
    hole_1.lineTo(w/2-w/100,h/100)
    hole_1.lineTo(w/2-w/100,h-h/100)
    hole_1.lineTo(w/100,h-h/100)

    const hole_2 = new Path()
    hole_2.moveTo(w/2+w/100,h/100)
    hole_2.lineTo(w-w/100,h/100)
    hole_2.lineTo(w-w/100,h-h/100)
    hole_2.lineTo(w/2+w/100,h-h/100)

    shape.holes.push(hole_1)
    shape.holes.push(hole_2)
  
    const extrudeSettings = { 
      depth: 0.1, 
      bevelEnabled: true, 
      bevelSegments: 2, 
      steps: 2, 
      bevelSize: 0.5, 
      bevelThickness: 0.1
    };
  
    const geometry = new ExtrudeGeometry( shape, extrudeSettings );
    const frameMaterial = new MeshLambertMaterial({ 
      color: 0xc2bec1
    })
    const frame = new Mesh( geometry, frameMaterial )
    window.add(frame)

    // 窗户玻璃 
    const glassGeometry = new BoxBufferGeometry( w, h, 1 )
    const glassMaterial = new MeshPhysicalMaterial( {
      color: 0xcfcfcf,
      metalness: 0,
      roughness: 0,
      opacity: 0.3,
      transparent: true,
      envMapIntensity: 10,
      premultipliedAlpha: true
    } )
    const glass = new Mesh( glassGeometry, glassMaterial )
    glass.position.set(w/2,h/2,0)
    window.add(glass)

    window.name = name
    this.instance.add(window)
    return window
  }

  addDoor () {
    const geometry = new BoxBufferGeometry( this.length/15, this.height-this.height/4, 1 )
    const material = new THREE.MeshPhongMaterial({
      color:0x68686b,
      side:THREE.DoubleSide,
      opacity:0.8,
    })
    const door = new Mesh( geometry, material )
    door.position.set(this.width/2,(this.height-this.height/4)/2,0)
    door.rotation.y = Math.PI/2
    door.name = '门'
    this.instance.add( door )
  }
}

 diector.js中创建

addHouse(){
    const house = new House(150,80,20,this.scene)
    console.log(house);
    house.setPosition(0, 1, 0)
    house.addToScene(this.scene)
    this.meshList.push(...house.instance.children)
  }

添加物品box,这里只写了五个想接着多写可以自己写规律

addBox(){
    let w=6
    let x_length = 0
    let y_length = 0
    let z_length = 0
    let boxgroup = new THREE.Group()
    const geometry = new THREE.BoxBufferGeometry(w,w,w)
    const material = new THREE.MeshLambertMaterial({
      color:0xb99b75
    })
    for (let index = 1; index <= 5; index++) {
      if(index%2 == 0){
        x_length += w
      }else if(index%3 == 0){
        x_length -= w , z_length += w
      }else if(index%4 == 0){
        x_length += w
      }else if(index%5 == 0){
        x_length -= w , y_length += w , z_length -= w
      }else{
        x_length += w/2 , y_length += w/2 , z_length += w/2
      }
      let box = new THREE.Mesh(geometry, material)
      box.name = '盒子'+index
      let edges = new THREE.EdgesHelper( box, 0x000000 );//设置边框,可以旋转
      box.name = '盒子边框'+index
      box.position.set(x_length,y_length,z_length)
      edges.position.set(x_length,y_length,z_length)

      boxgroup.add(box)
      boxgroup.add( edges );
      this.meshList.push(box,edges)
    }
    boxgroup.position.set(-10,0,20)
    this.scene.add(boxgroup)
  }

给门加动画特效,点击开门关门

addMouseDown(){
    console.log(this.intersects);
    // 门特效
    let list = this.intersects.filter((item)=>item.object.name == '门')
    if(list.length > 0){
      if(this.doorstatus == 'close'){
        list[0].object.rotateY(-Math.PI / 2);
        list[0].object.translateOnAxis(new THREE.Vector3(0, 0, 1),                 list[0].object.geometry.parameters.width/2);
        list[0].object.translateOnAxis(new THREE.Vector3(1, 0, 0), list[0].object.geometry.parameters.width/2);
        this.doorstatus = 'open'
      }else{
        list[0].object.rotateY(Math.PI/2);
        list[0].object.translateOnAxis(new THREE.Vector3(0, 0, 1), -list[0].object.geometry.parameters.width/2);
        list[0].object.translateOnAxis(new THREE.Vector3(1, 0, 0), list[0].object.geometry.parameters.width/2);
        this.doorstatus = 'close'
      }
    }
  }

完整代码director.js如下,house.js如上,其余three.js教程学习初始化配置

调用new Director(document.querySelector('#threeBox'))即可

import Template from "../common/Template"
import * as THREE from 'three'
import House from "../objects/House"
import TWEEN from '@tweenjs/tween.js'
export default class Director extends Template{
  constructor (ele) {
    super()
    this.ele = ele
    this.PCamera.fov = 45
    this.PCamera.far = 10000
    this.PCamera.near = 1
    this.rendererColor = new THREE.Color(0x01031c)
    this.cameraPostion = new THREE.Vector3(150, 100, 0)

    this.init(this.ele)
    this.addLight() 
    this.addAxesHelper(1000)
    if(this.camera && this.renderer) this.addOrbitControls(this.camera, this.renderer.domElement);
    this.animate()
    this.addGround()
    this.addHouse()
    this.addBox()
    // 监听鼠标点击
    this.status = 'close'
    this.onMouseDown(this.addMouseDown.bind(this))
  }
  addMouseDown(){
    console.log(this.intersects);
    // 门特效
    let list = this.intersects.filter((item)=>item.object.name == '门')
    if(list.length > 0){
      if(this.doorstatus == 'close'){
        list[0].object.rotateY(-Math.PI / 2);
        list[0].object.translateOnAxis(new THREE.Vector3(0, 0, 1), list[0].object.geometry.parameters.width/2);
        list[0].object.translateOnAxis(new THREE.Vector3(1, 0, 0), list[0].object.geometry.parameters.width/2);
        this.doorstatus = 'open'
      }else{
        list[0].object.rotateY(Math.PI/2);
        list[0].object.translateOnAxis(new THREE.Vector3(0, 0, 1), -list[0].object.geometry.parameters.width/2);
        list[0].object.translateOnAxis(new THREE.Vector3(1, 0, 0), list[0].object.geometry.parameters.width/2);
        this.doorstatus = 'close'
      }
    }
  }
  addBox(){
    let w=6
    let x_length = 0
    let y_length = 0
    let z_length = 0
    let boxgroup = new THREE.Group()
    const geometry = new THREE.BoxBufferGeometry(w,w,w)
    const material = new THREE.MeshLambertMaterial({
      color:0xb99b75
    })
    for (let index = 1; index <= 5; index++) {
      if(index%2 == 0){
        x_length += w
      }else if(index%3 == 0){
        x_length -= w , z_length += w
      }else if(index%4 == 0){
        x_length += w
      }else if(index%5 == 0){
        x_length -= w , y_length += w , z_length -= w
      }else{
        x_length += w/2 , y_length += w/2 , z_length += w/2
      }
      let box = new THREE.Mesh(geometry, material)
      box.name = '盒子'+index
      let edges = new THREE.EdgesHelper( box, 0x000000 );//设置边框,可以旋转
      box.name = '盒子边框'+index
      box.position.set(x_length,y_length,z_length)
      edges.position.set(x_length,y_length,z_length)

      boxgroup.add(box)
      boxgroup.add( edges );
      this.meshList.push(box,edges)
    }
    boxgroup.position.set(-10,0,20)
    this.scene.add(boxgroup)
  }
  addHouse(){
    const house = new House(150,80,20,this.scene)
    console.log(house);
    house.setPosition(0, 1, 0)
    house.addToScene(this.scene)
    this.meshList.push(...house.instance.children)
  }
  addGround(){
    const groundGeometry = new THREE.PlaneGeometry(150,250)
    const groundMaterial = new THREE.MeshLambertMaterial({
      color:0x454942
    })

    let ground = new THREE.Mesh(groundGeometry, groundMaterial)
    ground.rotation.x = -Math.PI/2
    ground.name = '地'
    this.scene.add(ground)
    this.meshList.push(ground)
  }
  addLight(){
    this.addAmbientLight(0x666666)
    this.addDirectionalLight(0xdfebff,{x:50, y:200, z:100},1)
  }
  animate () {
    // 执行运动动画
    if(this.renderer && this.camera){
      this.renderer.render(this.scene, this.camera)
      requestAnimationFrame(this.animate.bind(this))
      TWEEN.update();
    }
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值