CSS2DRenderer

这是一个2D的render,可以在页面中渲染出一个div标签。下图中的城市名称就是渲染出来的,所以地图旋转的时候文字依然能够保持直立和水平。很实用的一个功能。

three.js CSS2DRenderer

    let laberDiv = document.createElement('div');//创建div容器
    laberDiv.className = 'label';
    laberDiv.textContent = cityname;
    laberDiv.style.marginTop = '-1em';
    let pointLabel = new CSS2DObject(laberDiv);   
    pointLabel.position.set(x, y,z);    
    scene.add(pointLabel);

    labelRenderer = new CSS2DRenderer(); //新建CSS2DRenderer 
    labelRenderer.setSize(divWidth, divHeight);
    labelRenderer.domElement.style.position = 'absolute';
    labelRenderer.domElement.style.top = 0;
    document.getElementById(webglDivId).appendChild(labelRenderer.domElement);

 	controls = new OrbitControls(camera); //加renderer.domElement,会不灵光
	renderer.render(scene, camera);
    labelRenderer.render( scene, camera );//渲染

源码,简单的修改了一下使能够import { CSS2DRenderer, CSS2DObject } from "CSS2DRenderer",用在webpack开发的项目中。主要把类似 THREE.CSS2DObject的改成 var CSS2DObject等修改。在调用的时候前面也不需要加THREE。
和控制器一起使用的时候有个问题。页面中共有Renderer,labelRenderer 两个randerer。一个渲染出canvas,一个是div。大小相同,位置重叠,div会在canvas上面显示。所以在(camera,renderer.domElement)中,renderer.domElement会在labelRenderer.domElement下面而导致 controls无法触发。所以要把这个地方换成labelRenderer.domElement或者不写。不写默认是document,会在整个页面触发控制事件,单页满屏的时候没关系,在窗口模式的时候就出现了不理想的情况。
使用了CSS2DRenderer之后,在重置窗口的时候也需要重置一下。

源码研究一下:

/**
 * @author mrdoob / http://mrdoob.com/
 */
import * as THREE from "three"
let CSS2DObject = function ( element ) {
	THREE.Object3D.call( this );
	this.element = element;
	this.element.style.position = 'absolute';
	this.addEventListener( 'removed', function ( event ) {
		if ( this.element.parentNode !== null ) {
			this.element.parentNode.removeChild( this.element );
		}
	} );
};

CSS2DObject.prototype = Object.create( THREE.Object3D.prototype );
CSS2DObject.prototype.constructor = CSS2DObject;

let CSS2DRenderer = function () {
	console.log( 'CSS2DRenderer', THREE.REVISION );
	var _width, _height;
	var _widthHalf, _heightHalf;
	var vector = new THREE.Vector3();
	var viewMatrix = new THREE.Matrix4();
	var viewProjectionMatrix = new THREE.Matrix4();

	var cache = {
		objects: new WeakMap()
	};

	var domElement = document.createElement( 'div' );
	domElement.style.overflow = 'hidden';
	this.domElement = domElement;

	this.getSize = function () {
		return {
			width: _width,
			height: _height
		};
	};

	this.setSize = function ( width, height ) {
		_width = width;
		_height = height;

		_widthHalf = _width / 2;
		_heightHalf = _height / 2;

		domElement.style.width = width + 'px';
		domElement.style.height = height + 'px';

	};

	var renderObject = function ( object, camera ) {
		if ( object instanceof CSS2DObject ) {
			vector.setFromMatrixPosition( object.matrixWorld );
			vector.applyMatrix4( viewProjectionMatrix );

			var element = object.element;
			var style = 'translate(-50%,-50%) translate(' + ( vector.x * _widthHalf + _widthHalf ) + 'px,' + ( - vector.y * _heightHalf + _heightHalf ) + 'px)';

			element.style.WebkitTransform = style;
			element.style.MozTransform = style;
			element.style.oTransform = style;
			element.style.transform = style;

			var objectData = {
				distanceToCameraSquared: getDistanceToSquared( camera, object )
			};

			cache.objects.set( object, objectData );
			if ( element.parentNode !== domElement ) {
				domElement.appendChild( element );
			}
		}

		for ( var i = 0, l = object.children.length; i < l; i ++ ) {
			renderObject( object.children[ i ], camera );
		}
	};
	var getDistanceToSquared = function () {
		var a = new THREE.Vector3();
		var b = new THREE.Vector3();
		return function ( object1, object2 ) {
			a.setFromMatrixPosition( object1.matrixWorld );
			b.setFromMatrixPosition( object2.matrixWorld );
			return a.distanceToSquared( b );
		};
	}();

	var filterAndFlatten = function ( scene ) {
		var result = [];
		scene.traverse( function ( object ) {
			if ( object instanceof CSS2DObject ) result.push( object );
		} );
		return result;
	};
	var zOrder = function ( scene ) {
		var sorted = filterAndFlatten( scene ).sort( function ( a, b ) {
			var distanceA = cache.objects.get( a ).distanceToCameraSquared;
			var distanceB = cache.objects.get( b ).distanceToCameraSquared;
			return distanceA - distanceB;
		} );

		var zMax = sorted.length;
		for ( var i = 0, l = sorted.length; i < l; i ++ ) {
			sorted[ i ].element.style.zIndex = zMax - i;
		}

	};

	this.render = function ( scene, camera ) {
		scene.updateMatrixWorld();
		if ( camera.parent === null ) camera.updateMatrixWorld();
		viewMatrix.copy( camera.matrixWorldInverse );
		viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, viewMatrix );
		renderObject( scene, camera );
		zOrder( scene );
	};
};
export {CSS2DRenderer,CSS2DObject}

嗯 很简单(怎么可能)……

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-12-22
  • 2022-12-23
  • 2021-11-15
  • 2021-12-22
相关资源
相似解决方案