diff --git a/examples/css2d_label.html b/examples/css2d_label.html
index ce6a7d10d8777f..85317677784ed6 100644
--- a/examples/css2d_label.html
+++ b/examples/css2d_label.html
@@ -80,7 +80,7 @@
const MOON_RADIUS = 0.27;
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 200 );
- camera.position.set( 10, 5, 20 );
+ camera.position.set( 5, 2, 10 );
camera.layers.enableAll();
scene = new THREE.Scene();
@@ -127,32 +127,37 @@
earthDiv.className = 'label';
earthDiv.textContent = 'Earth';
earthDiv.style.backgroundColor = 'transparent';
+ earthDiv.style.border = "1px solid white";
const earthLabel = new CSS2DObject( earthDiv );
earthLabel.position.set( 1.5 * EARTH_RADIUS, 0, 0 );
- earthLabel.center.set( 0, 1 );
+ earthLabel.center.set( 0, 1 ); // lower-left
earth.add( earthLabel );
earthLabel.layers.set( 0 );
+ earthLabel.rotationAngle = Math.PI / 8;
const earthMassDiv = document.createElement( 'div' );
earthMassDiv.className = 'label';
earthMassDiv.textContent = '5.97237e24 kg';
earthMassDiv.style.backgroundColor = 'transparent';
+ earthMassDiv.style.border = "1px solid white";
const earthMassLabel = new CSS2DObject( earthMassDiv );
earthMassLabel.position.set( 1.5 * EARTH_RADIUS, 0, 0 );
- earthMassLabel.center.set( 0, 0 );
+ earthMassLabel.center.set( 0, 0 ); // upper-left
earth.add( earthMassLabel );
earthMassLabel.layers.set( 1 );
+ earthMassLabel.rotationAngle = - Math.PI / 8;
const moonDiv = document.createElement( 'div' );
moonDiv.className = 'label';
moonDiv.textContent = 'Moon';
moonDiv.style.backgroundColor = 'transparent';
+ moonDiv.style.border = "1px solid white";
const moonLabel = new CSS2DObject( moonDiv );
moonLabel.position.set( 1.5 * MOON_RADIUS, 0, 0 );
- moonLabel.center.set( 0, 1 );
+ moonLabel.center.set( 0, 1 ); // lower-left
moon.add( moonLabel );
moonLabel.layers.set( 0 );
@@ -160,10 +165,11 @@
moonMassDiv.className = 'label';
moonMassDiv.textContent = '7.342e22 kg';
moonMassDiv.style.backgroundColor = 'transparent';
+ moonMassDiv.style.border = "1px solid white";
const moonMassLabel = new CSS2DObject( moonMassDiv );
moonMassLabel.position.set( 1.5 * MOON_RADIUS, 0, 0 );
- moonMassLabel.center.set( 0, 0 );
+ moonMassLabel.center.set( 0, 0 ); // upper-left
moon.add( moonMassLabel );
moonMassLabel.layers.set( 1 );
diff --git a/examples/jsm/renderers/CSS2DRenderer.js b/examples/jsm/renderers/CSS2DRenderer.js
index 4e350c711fad66..b4b88efb3fe884 100644
--- a/examples/jsm/renderers/CSS2DRenderer.js
+++ b/examples/jsm/renderers/CSS2DRenderer.js
@@ -46,14 +46,23 @@ class CSS2DObject extends Object3D {
this.element.setAttribute( 'draggable', false );
/**
- * The 3D objects center point.
- * `( 0, 0 )` is the lower left, `( 1, 1 )` is the top right.
+ * The object's anchor point, and the point around which the object rotates.
+ * A value of `(0.5, 0.5)` corresponds to the midpoint of the object. A value
+ * of `(0, 0)` corresponds to the upper left corner of the object.
*
* @type {Vector2}
* @default (0.5,0.5)
*/
this.center = new Vector2( 0.5, 0.5 );
+ /**
+ * The object's angle of rotation, counterclockwise, in radians.
+ *
+ * @type {number}
+ * @default 0
+ */
+ this.rotationAngle = 0;
+
this.addEventListener( 'removed', function () {
this.traverse( function ( object ) {
@@ -97,8 +106,7 @@ const _a = new Vector3();
const _b = new Vector3();
/**
- * This renderer is a simplified version of {@link CSS3DRenderer}. The only transformation that is
- * supported is translation.
+ * This renderer is a simplified version of {@link CSS3DRenderer}.
*
* The renderer is very useful if you want to combine HTML based labels with 3D objects. Here too,
* the respective DOM elements are wrapped into an instance of {@link CSS2DObject} and added to the
@@ -235,7 +243,20 @@ class CSS2DRenderer {
object.onBeforeRender( _this, scene, camera );
- element.style.transform = 'translate(' + ( - 100 * object.center.x ) + '%,' + ( - 100 * object.center.y ) + '%)' + 'translate(' + ( _vector.x * _widthHalf + _widthHalf ) + 'px,' + ( - _vector.y * _heightHalf + _heightHalf ) + 'px)';
+ // pivot point
+ const cx = 100 * object.center.x;
+ const cy = 100 * object.center.y;
+ element.style.transformOrigin = `${cx}% ${cy}%`;
+
+ // angle of rotation, counter-clockwise convention
+ const angle = - object.rotationAngle;
+
+ // coordinates
+ const tx = _vector.x * _widthHalf + _widthHalf;
+ const ty = -_vector.y * _heightHalf + _heightHalf;
+
+ // transform
+ element.style.transform = `translate(${-cx}%, ${-cy}%) translate(${tx}px, ${ty}px) rotate(${angle}rad)`;
if ( element.parentNode !== domElement ) {