美文网首页
THREE.js<物体的选中和文字提示>

THREE.js<物体的选中和文字提示>

作者: 誰在花里胡哨 | 来源:发表于2020-06-16 00:25 被阅读0次
效果图:
20200616.gif
对threejs的一些基础知识还不了解的,可以参考 此篇文章,去学习相关知识。

当然,在threejs中给物体添加文字备注的方法有很多种,此篇只是其中一种,主要是运用 css+html 创建标签,通过位置偏移实现的。(个人比较喜欢这种,文字什么的都可以自定义)

🎈下面是针对本篇文章实现效果提供的知识点和学习地址
知识点:
1. threejs的物体选中,主要是通过 光线投射Raycaster 进而计算得到的;

//获取到当前物体的相关属性值
 console.log(INTERSECTED);
//此处定义的是蓝色
//鼠标选中物体时的颜色
INTERSECTED.material.emissive.setHex(0x001aff);

🎐相关案例地址:http://www.webgl3d.cn/threejs/examples/#webgl_interactive_cubes

源代码可点击查看右下角

image.png
2. 如何给选中的物体添加文字标签
 //关键代码,把选中时物体的三维坐标转屏幕坐标
 //三维坐标转屏幕坐标的方法
    function transPosition(position) {
        let world_vector = new THREE.Vector3(position.x, position.y, position.z);
        let vector = world_vector.project(camera);
        let halfWidth = window.innerWidth / 2,
            halfHeight = window.innerHeight / 2;
        return {
            x: Math.round(vector.x * halfWidth + halfWidth),
            y: Math.round(-vector.y * halfHeight + halfHeight)
        };
    }

🎐参考地址:https://blog.csdn.net/qq_36266612/article/details/89851618

代码如下:
<!DOCTYPE html>
<html lang="en">

<head>
    <title>three.js webgl - interactive cubes</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <script src="http://www.yanhuangxueyuan.com/threejs/build/three.js"></script>
    <script src="http://www.yanhuangxueyuan.com/threejs/examples/js/controls/OrbitControls.js"></script>
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }

        #container {
            position: absolute;
            top: 0;
            left: 0;
            z-index: -1;
        }

        /* 文字提示框样式 */
        .text {
            display: none;
            box-shadow: 0 0 5px rgb(138, 138, 138);
            padding: 10px;
            position: relative;
            font-weight: bold;
            background: rgba(255, 255, 255, 0.747);
        }
    </style>
</head>

<body>
    <div class="text"></div>
    <div id="container"></div>
</body>


<script>

    var container; //创建容器
    var camera, scene, raycaster, renderer;

    var mouse = new THREE.Vector2(), INTERSECTED;
    var k = window.innerWidth / window.innerHeight; //窗口宽高比
    var s = 100; //三维场景显示范围控制系数,系数越大,显示的范围越大

    var textBox = document.querySelector('.text')

    //初始化
    function init() {
        //容器
        container = document.getElementById('container');
        document.body.appendChild(container);
        //场景
        scene = new THREE.Scene();
        scene.background = new THREE.Color(0xf0f0f0);
        //相机
        camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
        camera.position.set(300, 300, 800); //设置相机位置
        camera.lookAt(scene.position); //设置相机方向(指向的场景对象)

        //光源 
        var point = new THREE.PointLight(0xffffff, 1);
        point.position.set(300, 500, 300);
        scene.add(point);

        //创建网格模型  立方缓冲几何体
        var geometry = new THREE.BoxGeometry(20, 20, 20);

        for (var i = 0; i < 3; i++) {
            //给创建的几何体添加随机颜色
            var object = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({ color: Math.random() * 0xffffff }));
            object.name = '物体' + (i + 1);
            //随机位置
            object.position.x = i * 25;
            //添加到场景中
            scene.add(object);

        }
        // 光线投射Raycaster
        // 这个类用于进行raycasting(光线投射)。 光线投射用于进行鼠标拾取(在三维空间中计算出鼠标移过了什么物体)。
        // http://www.webgl3d.cn/threejs/docs/#api/zh/core/Raycaster
        raycaster = new THREE.Raycaster();

        // 创建渲染器对象
        renderer = new THREE.WebGLRenderer();
        // window.devicePixelRatio 获取更清晰的图像
        // https://www.w3cschool.cn/fetch_api/fetch_api-atvq2nma.html
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(window.innerWidth, window.innerHeight); //设置渲染区域尺寸

        //容器中插入canvas对象
        container.appendChild(renderer.domElement);

        //监听鼠标的位置移动,进而获取到指向物体
        document.addEventListener('mousedown', onDocumentMouseDown, false);
        //监听窗口发生改变时的方法
        window.addEventListener('resize', onWindowResize, false);

    }

    //窗口改变时重新进行渲染
    function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
    }

    //鼠标点击
    function onDocumentMouseDown(event) {
        event.preventDefault();
        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
    }

    //三维坐标转屏幕坐标的方法
    function transPosition(position) {
        let world_vector = new THREE.Vector3(position.x, position.y, position.z);
        let vector = world_vector.project(camera);
        let halfWidth = window.innerWidth / 2,
            halfHeight = window.innerHeight / 2;
        return {
            x: Math.round(vector.x * halfWidth + halfWidth),
            y: Math.round(-vector.y * halfHeight + halfHeight)
        };
    }

    //执行动画
    function animate() {
        requestAnimationFrame(animate);
        render();
    }

    // 渲染动画
    function render() {
        // 通过摄像机和鼠标位置更新射线
        raycaster.setFromCamera(mouse, camera);
        // 计算物体和射线的焦点
        var intersects = raycaster.intersectObjects(scene.children);

        //选中物体时
        if (intersects.length > 0) {
            if (INTERSECTED != intersects[0].object) {
                if (INTERSECTED) {
                    INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);
                }
                INTERSECTED = intersects[0].object;
                INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();

                //鼠标选中物体时的颜色
                INTERSECTED.material.emissive.setHex(0x001aff);
                //获取到当前物体的相关属性值
                console.log(INTERSECTED);

                //将选中物体的三维坐标转化
                var position = new THREE.Vector3(INTERSECTED.position.x, INTERSECTED.position.y, INTERSECTED.position.z);
                console.log((transPosition(position)))
                textBox.style.display = "inline-block"
                textBox.style.left = transPosition(position).x + 'px'
                textBox.style.top = transPosition(position).y + 'px'
                textBox.innerHTML = INTERSECTED.name
            }
        } else {
            //未选中物体时
            if (INTERSECTED) {
                INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);
                textBox.style.display = "none"
            }
            INTERSECTED = null;
        }
        renderer.render(scene, camera);
    }

    init();
    animate();
    //创建控件对象
    var controls = new THREE.OrbitControls(camera, renderer.domElement);
</script>

</html>

相关文章

网友评论

      本文标题:THREE.js<物体的选中和文字提示>

      本文链接:https://www.haomeiwen.com/subject/rwikxktx.html