JSFiddle - React, Tailwind, and code Playground

by Paul West

CSS

body{
  overflow: hidden;
  margin: 0;
}

.label {
  text-align: center;
  width: 20px;
  height: 20px;
  border: 1px solid white;
  border-radius: 10px;
  color: #4f8;
  font-family: sans-serif;
  background: rgba( 0, 0, 0, .6 );
}

JavaScript

import * as THREE from "https://cdn.skypack.dev/three@0.136.0";
import {OrbitControls} from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls.js";
import { CSS2DRenderer, CSS2DObject } from 'https://cdn.skypack.dev/three@0.136.0/examples/jsm/renderers/CSS2DRenderer.js';

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(10, 10, 10);
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

var labelRenderer = new CSS2DRenderer();
labelRenderer.setSize( innerWidth, innerHeight );
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = '0px';
document.body.appendChild( labelRenderer.domElement );

var controls = new OrbitControls(camera, labelRenderer.domElement);

var light = new THREE.DirectionalLight(0xffffff, 1.);
light.position.set(10, 20, 30);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.5));

scene.add(new THREE.GridHelper(10, 10));

var box = new THREE.Mesh(new THREE.BoxBufferGeometry(4, 2, 2), new THREE.MeshLambertMaterial({color: 0x0088ff, wireframe: false}));
scene.add(box);

var pos = new THREE.Vector3(2.1, 0, 0);
var normal = new THREE.Vector3().copy(pos).normalize();

var cNormal = new THREE.Vector3();
var cPos = new THREE.Vector3();
var m4 = new THREE.Matrix4();

var div = document.createElement( 'div' );
div.className = 'label';
div.textContent = '1';
div.style.marginTop = '-1em';
var label = new CSS2DObject( div );
label.position.copy(pos);
box.add( label );


renderer.setAnimationLoop(()=>{
	
  cNormal.copy(normal).applyMatrix3(box.normalMatrix);
  cPos.copy(pos).applyMatrix4(m4.multiplyMatrices(camera.matrixWorldInverse, box.matrixWorld));
  let d = cPos.negate().dot(cNormal);
  
  div.style.visibility = d < 0 ? "hidden" : "visible";
  //div.style.opacity = d < 0 ? 0.25 : 1;
 ...