ThreeJS动态加载div标签

时间:2024-04-04 10:33:13

html中标签样式:

  .tap{
            position: absolute;
            background-color: MidnightBlue;
            background-color:rgba(0,10,40);
            border-top-left-radius: 10px;
            border-bottom-right-radius:10px;
            opacity: 0.5;
            font-size: 4px;
            color: aqua;
            width: 36px;
            height: 44px;
            padding: 1px 1px 1px;
        }

js中动态添加

//txt1 txt2 txt3 为div中要显示的文本,具体样式可修改 innerHTML那一行
function addDom(txt1,txt2,txt3) {
    let addDivDom = document.createElement('div');
    let bodyDom = document.body;
    bodyDom.insertBefore(addDivDom, bodyDom.lastChild);
    addDivDom.classList = 'tap';
    addDivDom.innerHTML = '<span style="color:white;font-size: 10px;padding: 5px">' + txt1 + '</span>'+'<span style="font-size: 11px;font-weight: bold">'+txt2+'</span>'+'<p style="padding: 5px;margin-top: -3px;">'+txt3+'</p>';
}
 

render中要实时渲染修改标签的二维坐标,代码中的position为三维坐标,即标签插入时的三维坐标

function renderLabel(){
            div.style.left=transPosition(position).x + 'px';
            div.style.top=transPosition(position).y + 'px';
}
//三维坐标转屏幕坐标
  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)
        };
    }

具体实例1:给建筑物添加标签
效果图:
ThreeJS动态加载div标签
ThreeJS动态加载div标签
(图一标签为颜色最暗的建筑的标签,图二为最高的建筑的标签)

    let build=new THREE.Group();
    var loader = new THREE.VRMLLoader();
    //加载一个wrl格式的模型,其他格式模型同样,自建cube等不需要自建box
    loader.load( 'model/h.wrl', function ( object ) {

        object.castShadow = true;

        build= object.children[0].children[0];
        build.castShadow = true;
        object.position.x=-20;
        object.position.y=0;
        object.position.z=-30;

        scene.add(object);
        let box= creatBoundingBox(object);
        build.box=box;
         addDom("楼宇名称  ","h 可点击","占地面积:25541平方米",box);
        CubeArray.push(box);
        })
        
function addDom(txt1,txt2,txt3,cube) {
    let addDivDom = document.createElement('div');
    let bodyDom = document.body;
    bodyDom.insertBefore(addDivDom, bodyDom.lastChild);
    addDivDom.id=cube.uuid+"_text";
    addDivDom.classList = 'tap';
    addDivDom.innerHTML = '<span style="color:white;font-size: 10px;padding: 5px">' + txt1 + '</span>'+'<span style="font-size: 11px;font-weight: bold">'+txt2+'</span>'+'<p style="padding: 5px;margin-top: -3px;">'+txt3+'</p>';
    divIdArray.push(addDivDom.id);
}
 //渲染实时更新标签位置
function render() {
    cubeLabe();
    renderer.render(scene, camera);
}
//只显示最近点击的楼的标签 其他标签隐藏不显示
function cubeLabe() {
    if(IsSelectedMesh==true)
    {
        let cube=clickmesh;
        let divid=cube.uuid+"_text";
        for(let i=0;i<divIdArray.length;i++) {
            let id = divIdArray[i];
            let div = document.getElementById(id);
            if(id==divid)
            {
                if(div!=null&&div!=undefined){
                    div.style.display="";
                    div.style.left=interface.transPosition(cube.position).x + 'px';
                    let posi=new THREE.Vector3(cube.position.x,(cube.position.y)*2,cube.position.z);
                    div.style.top=interface.transPosition(posi).y-100 + 'px';
                    // let number=cube.uuid;
                    // div.style.zIndex=number;
                }
            }else {
                if(div!=null&&div!=undefined){
                    div.style.display = "none";
                }

            }
        }
    }else {
        for(let i=0;i<divIdArray.length;i++) {
            let id = divIdArray[i];
            let div = document.getElementById(id);

            if(div!=null||div!=undefined){
                div.style.display = "none";
            }
        }
    }
}
//生成模型包围盒实体,方便标签判断位置
function creatBoundingBox(object) {
    //计算包围盒长宽高
    let Box=new THREE.Box3();
    Box.setFromObject(object);
    if ( Box.isEmpty() ) return;
    let min = Box.min;
    let max = Box.max;
    let width=max.x-min.x;
    let height=max.y-min.y;
    let deepth=max.z-min.z;
    // console.log(width+";"+height+";"+deepth);

    //计算包围盒中心点
    let centerX=(max.x+min.x)/2;
    let centerY=(max.y+min.y)/2;
    let centerZ=(max.z+min.z)/2;

    //画一个boundingbox的cube实体

    let boxGeometry=new THREE.BoxGeometry(width,height,deepth);
    let boxMaterial=new THREE.MeshLambertMaterial({});
    let box=new THREE.Mesh(boxGeometry,boxMaterial);
    box.position.set(centerX,centerY,centerZ);
    return box;
}

具体实例2 点击模型表面添加标签,标签为图片
效果图:
ThreeJS动态加载div标签
ThreeJS动态加载div标签

    var fixedBoard = function () {
        position:null;
        div:null;
        image:null
    }
    var fixedBoardlist=[];
    //添加鼠标事件 移除鼠标事件
    function ImageTag() {
        addEventListener('click',addFixedBoard);// 监听窗口鼠标单击事件
        $(document).keydown(function (event) {
            if (event.keyCode == 27) {
                removeAddBoard();
            }
        });
    }
//固定位置的标签
    function addFixedBoard() {
        var windowX = event.clientX;//鼠标单击位置横坐标
        var windowY = event.clientY;//鼠标单击位置纵坐标

        var addDivDom = document.createElement('div');
        var bodyDom = document.body;
        bodyDom.insertBefore(addDivDom, bodyDom.lastChild);
        // addDivDom.id=cube.uuid+"_text";
        addDivDom.classList = 'tap';
        var img=new Image();
        // var image=document.createElement("img");
        var  image_src="./img/002.png";
        img.src=image_src;
        addDivDom.appendChild(img);


        var x = (windowX / window.innerWidth) * 2 - 1;//标准设备横坐标
        var y = -(windowY / window.innerHeight) * 2 + 1;//标准设备纵坐标
        var standardVector = new THREE.Vector3(x, y, 0.5);//标准设备坐标
        //标准设备坐标转世界坐标
        var worldVector = standardVector.unproject(camera);
        var ray = worldVector.sub(camera.position).normalize();
        //创建射线投射器对象
        var raycaster = new THREE.Raycaster(camera.position, ray);
        //返回射线选中的对象
        var intersects = raycaster.intersectObjects(floorChildrenGroup);
        console.log(intersects);
        if (intersects.length > 0) {
            var point=intersects[0].point;
            var board=new fixedBoard();
            board.position=point;
            board.div=addDivDom;
            board.image=img;
            fixedBoardlist.push(board);
        }

    }
//移除鼠标单击事件绑定
    function removeAddBoard() {
        removeEventListener('click',addFixedBoard);
    }
//实时修改渲染时的图片位置
    function imagePosition() {
        for(var i=0;i<fixedBoardlist.length;i++){
            var position=fixedBoardlist[i].position;
            var div=fixedBoardlist[i].div;
            var x=interface.transPosition(position).x;
            var y=interface.transPosition(position).y;
            var image=fixedBoardlist[i].image;
            var width=image.width;
            var height=image.height;
            div.style.top=y-height+ 'px';
            div.style.left=x-width/2+ 'px';

        }
    }
//报警标签
    function Warning(Istrue) {
        if(Istrue){

            for(var i=0;i<fixedBoardlist.length;i++){
                fixedBoardlist[i].image.src='./img/003.png';
            }
            var button0=document.getElementById('warn');
            button0.style.display="none";
            var button1=document.getElementById('cancelwarn');
            button1.style.display="";
        }else {
            for(var i=0;i<fixedBoardlist.length;i++){
                fixedBoardlist[i].image.src='./img/002.png';
            }
            var button0=document.getElementById('warn');
            button0.style.display="";
            var button1=document.getElementById('cancelwarn');
            button1.style.display="none";
        }
    }
function render(){
    renderer.render(scene, camera);
    imagePosition();
}