ThreeJS教程:鼠标选中模型弹出标签(工厂)

推荐:将NSDT场景编辑器加入你的3D工具链
3D工具集:NSDT简石数字孪生

鼠标选中模型弹出标签(工厂)

射线、标签等知识点都学习过,你可以把本节课作为练习题,实现鼠标点击模型,弹出标签的功能。

添加HTML元素标签,并隐藏

引入标签的HTML、CSS代码,在射线拾取模型对象之前注意先隐藏display: none;

<div id="tag" style="display: none;">

HTML元素转化为CSS2模型对象

// 引入CSS2模型对象CSS2DObject
import {
    CSS2DObject
} from 'three/addons/renderers/CSS2DRenderer.js';
const div = document.getElementById('tag');
div.style.top = '-161px'; //指示线端点和标注点重合
// HTML元素转化为threejs的CSS2模型对象
const tag = new CSS2DObject(div);
export default tag;

设置CSS2渲染器代码

// 引入CSS2渲染器CSS2DRenderer
import {CSS2DRenderer} from 'three/addons/renderers/CSS2DRenderer.js';
// 创建一个CSS2渲染器CSS2DRenderer
const css2Renderer = new CSS2DRenderer();
css2Renderer.setSize(width, height);
// HTML标签<div id="tag"></div>外面父元素叠加到canvas画布上且重合
css2Renderer.domElement.style.position = 'absolute';
css2Renderer.domElement.style.top = '0px';
//设置.pointerEvents=none,解决HTML元素标签对threejs canvas画布鼠标事件的遮挡
css2Renderer.domElement.style.pointerEvents = 'none';
document.body.appendChild(css2Renderer.domElement);
// 渲染循环
function render() {
    css2Renderer.render(scene, camera);
    // ...
    requestAnimationFrame(render);
}

在射线代码基础上,添加标签代码

当发生鼠标事件,如果射线拾取到模型对象,就把标签做为选中模型的子对象,或作为选中模型对应标注点空对象的子对象。

前面说过,如果你想标注工厂中模型,CSS2模型对象有两种定位方式,下面两种定位模型位置方法任选其一即可。

需要标注的模型,把局部坐标系坐标原点设置在需要标注的位置

if (intersects.length > 0) {
    // 通过.ancestors属性判断那个模型对象被选中了
    outlinePass.selectedObjects = [intersects[0].object.ancestors];
    //tag会标注在intersects[0].object.ancestors模型的局部坐标系原点位置
    intersects[0].object.ancestors.add(tag);
}

工厂模型添加一个空对象,用来标记需要标注的位置。

标注点对应空对象命名规则和代码规则息息相关,模型中两个设备的名字是设备A设备B,对应的标注点空对象命名分别为设备A标注设备B标注

if (intersects.length > 0) {
    // 通过.ancestors属性判断那个模型对象被选中了
    outlinePass.selectedObjects = [intersects[0].object.ancestors];
    // 获取模型对象对应的标注点
    // console.log('intersects[0].object.ancestors.name',intersects[0].object.ancestors.name);
    const obj = model.getObjectByName(intersects[0].object.ancestors.name+'标注');
    //tag会标注在空对象obj对应的位置
    obj.add(tag);
}

没有选中模型,不显示标签和发光描边

在射线鼠标事件函数外面声明一个变量chooseObj来表示,此时是否有模型处于选中状态,如果没有,就把标签和发光描边取消。

let chooseObj = null;
addEventListener('click', function (event) {
    // ...射线拾取的代码
    // 射线交叉计算拾取模型
    const intersects = raycaster.intersectObjects(cunchu.children);
    if (intersects.length > 0) {
        // 通过.ancestors属性判断那个模型对象被选中了
        outlinePass.selectedObjects = [intersects[0].object.ancestors];
        //tag会标注在intersects[0].object.ancestors模型的局部坐标系原点位置
        intersects[0].object.ancestors.add(tag);
        chooseObj = intersects[0].object.ancestors;
    }else{
        if(chooseObj){//把原来选中模型对应的标签和发光描边隐藏
            outlinePass.selectedObjects = [];//无发光描边
            chooseObj.remove(tag);//从场景移除
        }
    }
})

修改标签内容

可以根据选中的设备设置对应的标签内容数据,下面只是以设备名称为例进行演示,其它的标签数据,也可以类似修改。

<span id="name">设备A</span>
// 获取设备名称标签
const span = document.getElementById('name');
addEventListener('click', function (event) {
    // ...
    // ...
    // 射线交叉计算拾取模型
    const intersects = raycaster.intersectObjects(cunchu.children);
    if (intersects.length > 0) {
        span.innerHTML = intersects[0].object.ancestors.name;//修改标签数据
    }
})

上一篇:ThreeJS教程:标签指示线或箭头指向标注点 (mvrlink.com)

下一篇:ThreeJS教程:鼠标选中模型弹出标签(工厂) (mvrlink.com)

NSDT场景编辑器 | NSDT 数字孪生 | GLTF在线编辑器 | 3D模型在线转换 | UnrealSynth虚幻合成数据生成器 | 3D模型自动纹理化工具
2023 power by nsdt©鄂ICP备2023000829号