示例效果:在这里插入图片描述
前言: 中间的图像块内容构建涉及保密数据,不做说明。只做如题相关的代码及说明。

拖拽

这里使用的是 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
})
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐