Three JS Keep Label Size On Zoom

前端 未结 4 537
臣服心动
臣服心动 2020-12-05 16:08

I\'m working on a solar system in three.js and am curious if there is an easy way to make the labels for the planets I have below all show up the same size regardless of how

4条回答
  •  情歌与酒
    2020-12-05 16:14

    Finally I found the answer to your question:

    First, create a DOM Element:

    Not Earth

    Then set CSS styles for it:

    .element {position: absolute; top:0; left:0; color: white}
    //        |-------------------------------|  |-----------|
    //            make the element on top of       canvas is 
    //               the canvas                   black, so text
    //                                            must be white
    

    After that, create moveDom() function and run it every time you render the scene requestAnimationFrame()

    • geometry is the geometry of the mesh
    • cube is the mesh you want to create label
        var moveDom = function(){
        vector = geometry.vertices[0].clone();
        vector.applyMatrix4(cube.matrix);
        vector.project(camera);
        vector.x = (vector.x * innerWidth/2) + innerWidth/2;
        vector.y = -(vector.y * innerHeight/2) + innerHeight/2;
        //Get the DOM element and apply transforms on it
        document.querySelectorAll(".element")[0].style.webkitTransform = "translate("+vector.x+"px,"+vector.y+"px)";
        document.querySelectorAll(".element")[0].style.transform = "translate("+vector.x+"px,"+vector.y+"px)";
        };
    

    You can create a for loop to set label for all the mesh in your scene.

    Because this trick only set 2D position of DOM Element, the size of label is the same even if you zoom (the label is not part of three.js scene).

    Full test case: https://jsfiddle.net/0L1rpayz/1/

    var renderer, scene, camera, cube, vector, geometry;
    
    var ww = window.innerWidth,
    	wh = window.innerHeight;
    
    function init(){
    
    	renderer = new THREE.WebGLRenderer({canvas : document.getElementById('scene')});
    	renderer.setSize(ww,wh);
    
    	scene = new THREE.Scene();
    
    	camera = new THREE.PerspectiveCamera(50,ww/wh, 0.1, 10000 );
    	camera.position.set(0,0,500);
    	scene.add(camera);
    
    	light = new THREE.DirectionalLight(0xffffff, 1);
    	light.position.set( 0, 0, 500 );
    	scene.add(light);
    
    	//Vector use to get position of vertice
    	vector = new THREE.Vector3();
    
    	//Generate Not Earth
    	geometry = new THREE.BoxGeometry(50,50,50);
    	var material = new THREE.MeshLambertMaterial({color: 0x00ff00});
      cube = new THREE.Mesh(geometry, material);
      scene.add(cube);
    	//Render my scene
    	render();
    }
    var moveDom = function(){
        vector = geometry.vertices[0].clone();
        vector.applyMatrix4(cube.matrix);
        vector.project(camera);
    	  vector.x = (vector.x * ww/2) + ww/2;
    	  vector.y = -(vector.y * wh/2) + wh/2;
    
        //Get the DOM element and apply transforms on it
       	document.querySelectorAll(".element")[0].style.webkitTransform = "translate("+vector.x+"px,"+vector.y+"px)";
       	document.querySelectorAll(".element")[0].style.transform = "translate("+vector.x+"px,"+vector.y+"px)";
    };
    
    
    var counter = 0;
    var render = function (a) {
    	requestAnimationFrame(render);
    
    	counter++;
    
    	//Move my cubes
    		cube.position.x = Math.cos((counter+1*150)/200)*(ww/6+1*80);
    		cube.position.y = Math.sin((counter+1*150)/200)*(70+1*80);
    		cube.rotation.x += .001*1+.002;
    		cube.rotation.y += .001*1+.02;
    
    		//Move my dom elements
    		moveDom();
    	
    	renderer.render(scene, camera);
    };
    
    init();
    body,html, canvas{width:100%;height:100%;padding:0;margin:0;overflow: hidden;}
    .element{color:white;position:absolute;top:0;left:0}
    
    
    	
    	

    Not Earth

    If you downvote this, please tell me why. I will try my best to improve my posts.

提交回复
热议问题