three.js 拖拽剪切构成剖面图
·
示例效果:
前言: 中间的图像块内容构建涉及保密数据,不做说明。只做如题相关的代码及说明。
拖拽
这里使用的是 DragControls这个类
该类提供一个drag 和drop 的交互。使用方法很简单,将需要挂载事件的object3D 对象数组、相机实例、dom传进去即可。
实例代码
// 注册事件.
registerRaycsterEvent: function (objects) {
//点击射线
let _this = this
let controls = new DragControls(
objects,
this.camera,
this.renderer.domElement
)
let header = wrfData.header
let [minLon, minLat, maxLon, maxLat] = [
header.lo1,
header.la1,
header.lo2,
header.la2,
]
let [lonDiff, latDiff] = [maxLon - minLon, maxLat - minLat]
console.log(_this.orbitControls);
controls.addEventListener('hoveron',function(){
_this.orbitControls.enabled = false
})
controls.addEventListener('hoveroff',function(){
_this.orbitControls.enabled = true
})
// 简单说下处理逻辑: 首先 将原物体的三维矩阵自动更新 取消,由 我们自己控制矩阵的更新
// 接着 拖动的过程中 会实时的修改xyz ,修改需要变化的 ,不变的 用回 初始值 ,即可保证他在某一轴上移动
// 接着 修改 截面的 constant 距离 即可.
controls.addEventListener('drag', function (evt) {
let targetObj = evt.object
if (targetObj.name == 'xring') {
targetObj.position.setY(-45 * 0.5)
targetObj.position.setZ(maxLat + 5)
// + 1 的理由是 覆盖掉整个X轴.
if (targetObj.position.x > maxLon + 1) {
targetObj.position.setX(maxLon + 1)
} else if (targetObj.position.x < minLon) {
targetObj.position.setX(minLon)
}
_this.xPlane.constant = -targetObj.position.x
} else if(targetObj.name == 'yring'){
targetObj.position.setX(maxLon + 3)
targetObj.position.setZ(minLat)
if(targetObj.position.y > 40 * 0.5 - 1){
targetObj.position.setY( 40 * 0.5 - 1)
} else if(targetObj.position.y < -45 * 0.5 - 1){
targetObj.position.setY(-45 * 0.5 - 1)
}
_this.yPlane.constant = targetObj.position.y
} else if(targetObj.name == 'zring'){
targetObj.position.setY(-45 * 0.5)
targetObj.position.setX(maxLon + 5)
if(targetObj.position.z > maxLat){
targetObj.position.setZ(maxLat)
} else if(targetObj.position.z < minLat){
targetObj.position.setZ(minLat)
}
_this.zPlane.constant = targetObj.position.z
}
targetObj.updateMatrix()
})
controls.activate()
},
- 抛开其余的细枝末节,关注重点,这里我的需求是需要拖拽某个物体在某一个范围内移动,同时限定为一个维度轴即:x,y,z;
- 当鼠标滑动所在的地方存在传进来的object3D 对象时,会触发这个hoveron事件,此时,为了让我们的拖拽事件正常,通常是需要把原来的控制事件禁用的。当然,当我们离开的时候要记得把他打开。
- drag会默认的改变物体的位置矩阵,所以,需要对你的targetObj即触发事件的object3D对象的matrixAutoUpdate设置为false,在设置初始值时显示的调用updateMatrix。例如:
let mesh = new THREE.Mesh(geometry,material)
// 先设置位置 让它先更新初始位置.
mesh.position.set()
mesh.martixAutoUpdate = false
// 想要更新 在 threejs 空间里的显示时,
mesh.position.set(?)
mesh.updateMatrix()
截面
使用的是Plane 这个类,这里主要是用于搭配材质的clippingPlanes属性 进行裁切。
什么是平面法向量?通俗的来说,就是垂直于一个平面的向量。如果不是很理解作用也没关系,可以使用PlaneHelper 查看下这些不同。为了保持文章精简,就只提供效果图,不做这部分的内容说明。
此时向右推进的平面为默认值1,0,0, constant 为 -minLon 。此内容请自己尝试。
任意的材质都继承自Material 这个基类,所以挂载在此类上的
此属性可以直接使用。
示例代码
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
clippingPlanes: [xPlane, yPlane, zPlane],
})
// 在初始化render器的阶段, 设置 可以被裁切.
var renderer = new THREE.WebGLRenderer()
renderer.localClippingEnabled = true
联动结合
controls.addEventListener('hoveron',function(){
// 屏蔽其他控制器事件.
_this.orbitControls.enabled = false
})
controls.addEventListener('hoveroff',function(){
_this.orbitControls.enabled = true
})
let _this = this
dragControl.addEventListener('drag',function(evt){
// 当前触发拖动的
let targetObj = evt.object
// 将不需要变化的维度 设置回原来的 因为默认会修改此 target的位置. 如果你设置了不自动更新此对象的位置矩阵,那么它将不会有任何视图上的改变.
targetObj.position.setY,Z,X()
// 最大最小值判断
if(x,y,z > max){} else if(x,y,z < min){}
// 设置好位置后 手动更新视图
targetObj.updateMatrix()
// 修改截面的constant 与 当前更新的 当前坐标轴 的位置 对应
_this.plane.constant = targetObj.position.x,y,z
})
更多推荐
已为社区贡献2条内容
所有评论(0)