一、原理:
transformcontrols 是由 three.js 提供的一类控制器。
该类可提供一种类似于在数字内容创建工具(例如blender)中对模型进行交互的方式,来在3d空间中变换物体。 和其他控制器不同的是,变换控制器不倾向于对场景摄像机的变换进行改变。
详见官网。
二、步骤:
- 初始化场景
- 引入transformcontrols控制器,并对其进行监听
- 添加模型和连线
- 根据控制器的改变对连线进行修改
三、代码:
<template>
<div class="fa_container">
<div class="container" ref="container"></div>
</div>
</template>
<script>
import * as three from 'three'
import { orbitcontrols } from 'three/examples/jsm/controls/orbitcontrols'
import { transformcontrols } from 'three/examples/jsm/controls/transformcontrols.js'
const scene = new three.scene()
let renderer = new three.webglrenderer({
antialias: true,
alpha: true,
logarithmicdepthbuffer: true
})
let camera, controls, transformcontrol
const pointer = new three.vector2()
const point = new three.vector3()
const raycaster = new three.raycaster()
let splinehelperobjects = []
const arc_segments = 200
let splines = []
export default {
name: 'model',
data () {
return {
positionlist: [
[10, 0, 0],
[-10, 0, 0]
]
}
},
mounted () {
this.init()
this.addmarkmodel()
this.render()
},
methods: {
init () {
this.dom = this.$refs['container']
this.inithelper()
this.initlight()
this.initcamera()
this.initrender()
this.initcontrols()
this.dom.addeventlistener('pointermove', e => {
this.onpointermove(e)
})
},
inithelper () {
scene.background = new three.color(0xf0f0f0)
// const axes = new three.axeshelper(50)
// scene.add(axes)
const planegeometry = new three.planegeometry(2000, 2000)
planegeometry.rotatex(-math.pi / 2)
const planematerial = new three.shadowmaterial({ color: 0x000000, opacity: 0.2 })
const plane = new three.mesh(planegeometry, planematerial)
plane.position.y = -200
plane.receiveshadow = true
scene.add(plane)
const helper = new three.gridhelper(2000, 100)
helper.position.y = -199
helper.material.opacity = 0.25
helper.material.transparent = true
scene.add(helper)
},
initcamera () {
camera = new three.perspectivecamera(
45,
this.dom.offsetwidth / this.dom.offsetheight,
0.001,
10000
)
camera.position.set(35, 35, 35)
},
initlight () {
const directlight = new three.directionallight('#ffffff', 0.5)
const directlight1 = new three.directionallight('#ffffff', 0.5)
const directlight2 = new three.pointlight('#ffffff', 0.5)
const ambientlight = new three.ambientlight('#ffffff', 0.3)
directlight.castshadow = true
directlight.position.set(15, 15, 15)
directlight1.position.set(-15, -15, 15)
ambientlight.position.set(0, 0, -5)
directlight2.position.set(-15, 15, -15)
directlight2.castshadow = true
scene.add(directlight, directlight1, ambientlight, directlight2)
},
initrender () {
renderer.setsize(1902, 935)
renderer.outputencoding = three.srgbencoding
this.dom.appendchild(renderer.domelement)
},
initcontrols () {
controls = new orbitcontrols(camera, renderer.domelement)
transformcontrol = new transformcontrols(camera, renderer.domelement)
transformcontrol.addeventlistener('change', () => {
console.log('模型拖动')
})
transformcontrol.addeventlistener('dragging-changed', function (event) {
controls.enabled = !event.value
})
transformcontrol.addeventlistener('objectchange', param => {
this.updatesplineoutline()
})
scene.add(transformcontrol)
},
// 鼠标移动
onpointermove (event) {
pointer.x = (event.clientx / window.innerwidth) * 2 - 1
pointer.y = -(event.clienty / window.innerheight) * 2 + 1
raycaster.setfromcamera(pointer, camera)
const intersects = raycaster.intersectobjects(splinehelperobjects, false)
if (intersects.length > 0) {
const object = intersects[0].object
if (object !== transformcontrol.object) {
transformcontrol.attach(object)
controls.enabled = false
}
}
},
// 更新连线
updatesplineoutline () {
for (let k = 0; k < splines.length; k++) {
const spline = splines[k]
const splinemesh = spline.mesh
const position = splinemesh.geometry.attributes.position
for (let i = 0; i < arc_segments; i++) {
const t = i / (arc_segments - 1)
spline.getpoint(t, point)
position.setxyz(i, point.x, point.y, point.z)
}
position.needsupdate = true
}
},
render () {
requestanimationframe(this.render.bind(this))
controls.update()
renderer.render(scene, camera)
},
addmarkmodel () {
for (let i = 0; i < this.positionlist.length; i++) {
let position = []
let obj1 = this.creatspot(this.positionlist[i], i)
let obj2 = this.creathtml(i)
settimeout(() => {
position.push(obj1.position)
position.push(obj2.position)
this.creatline(position)
}, 2000)
}
},
creatspot (positionarr, index) {
const sphergeometry = new three.spheregeometry(3, 32, 16)
const sphermaterial = new three.meshlambertmaterial({ color: 'red' })
const sphere = new three.mesh(sphergeometry, sphermaterial)
sphere.position.set(positionarr[0], positionarr[1], positionarr[2])
sphere.scale.set(0.2, 0.2, 0.2)
splinehelperobjects.push(sphere)
scene.add(sphere)
return sphere
},
creathtml (index, spot) {
const sphergeometry = new three.boxbuffergeometry(15, 15, 15)
const sphermaterial = new three.meshphongmaterial({
transparent: true,
opacity: 1,
color: 'green'
})
const sphere = new three.mesh(sphergeometry, sphermaterial)
sphere.position.x = math.random() * 10
sphere.position.y = math.random() * 20
sphere.position.z = math.random() * 15
sphere.scale.set(0.2, 0.2, 0.2)
splinehelperobjects.push(sphere)
scene.add(sphere)
return sphere
},
creatline (position) {
var curve = new three.catmullromcurve3(position)
var points = curve.getpoints(arc_segments)
var geometry = new three.buffergeometry().setfrompoints(points)
var material = new three.linebasicmaterial({ color: 0xff0000 })
curve.mesh = new three.linesegments(geometry, material)
scene.add(curve.mesh)
splines.push(curve)
}
}
}
</script>
<style>
.container {
width: 1902px;
height: 935px;
overflow: hidden;
background: black;
display: inline-block;
}
</style>
四、最终效果:
拖拽前:

鼠标拾取模型:

模型拖动:

总结
到此这篇关于three.js使用transformcontrols对模型拖拽的文章就介绍到这了,更多相关three.js对模型拖拽内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论