console
<div id="container"></div>
<script type="module">
import { TrackballControls } from 'https://threejs.org/examples/jsm/controls/TrackballControls.js';
import { CSS2DRenderer, CSS2DObject } from 'https://threejs.org/examples/jsm/renderers/CSS2DRenderer.js';
let camera, scene, renderer, labelRenderer;
let controls;
let root;
const offset = new THREE.Vector3();
const offsetOther = new THREE.Vector3();
const menu = document.getElementById( 'menu' );
init();
animate();
function init() {
let obj = document.getElementById( 'container' );
let objw = obj.clientWidth, objh = obj.clientHeight;
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xffffff );
camera = new THREE.OrthographicCamera( -objw /2, objw / 2, objh / 2, -objh/2, 1, 10000 );
camera.position.set(50, 50, 1000);
camera.lookAt(scene.position);
scene.add( camera );
const light1 = new THREE.DirectionalLight( 0xffffff, 0.8 );
light1.position.set( 1, 1, 1 );
scene.add( light1 );
const light2 = new THREE.DirectionalLight( 0xffffff, 0.5 );
light2.position.set( - 1, - 1, 1 );
scene.add( light2 );
root = new THREE.Group();
scene.add( root );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.getElementById( 'container' ).appendChild( renderer.domElement );
labelRenderer = new CSS2DRenderer();
labelRenderer.setSize( window.innerWidth, window.innerHeight );
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = '0px';
labelRenderer.domElement.style.pointerEvents = 'none';
document.getElementById( 'container' ).appendChild( labelRenderer.domElement );
controls = new TrackballControls( camera, renderer.domElement );
controls.minDistance = 1000;
controls.maxDistance = 2000;
controls.rotateSpeed = 2;
controls.zoomSpeed = 2;
controls.panSpeed = 1;
let buffGeometry = new THREE.BoxGeometry( 1, 1, 1 );
var geometry = new THREE.BufferGeometry();
let x = 4.42, y = 4.42, z = 2.91, scal = 75, leng=scal*6;
x *= scal;
y *= scal;
z *= scal;
let d = [
0,0,0,
x,0,0,
0,0,0,
0,y,0,
0,0,0,
0,0,z,
x,0,z,
x,0,0,
x,y,0,
0,y,0,
0,y,z,
x,y,z,
x,y,0,
x,y,z,
0,y,z,
0,0,z,
x,0,z,
x,y,z,
];
var vertices = new Float32Array(d);
var buff = new THREE.BufferAttribute( vertices, 3 );
geometry.addAttribute( 'position', buff);
var material = new THREE.PointsMaterial( {
color: 0x00fff0,
size:20 } );
var line = new THREE.Line( geometry, material );
scene.add( line );
var positions = geometry.attributes.position.clone();
const startbuff = new THREE.Vector3();
const endbuff = new THREE.Vector3();
geometry.computeBoundingBox();
geometry.boundingBox.getCenter( offsetOther ).negate();
geometry.translate( offsetOther.x, offsetOther.y, offsetOther.z );
let dirs = [{
name:'ax',
color:'red',
angTxt: 'r',
}, {
name:'by',
color:'green',
angTxt: '��',
},{
name:'cz',
color:'blue',
angTxt: '��',
},], ofx= offsetOther.x,ofy= offsetOther.y,ofz= offsetOther.z, labelren=[];
for ( let i = 0; i < 6; i += 2 ) {
startbuff.x = positions.getX( i ) + ofx;
startbuff.y = positions.getY( i ) + ofy;
startbuff.z = positions.getZ( i ) + ofz;
endbuff.x = positions.getX( i + 1 );
endbuff.y = positions.getY( i + 1 );
endbuff.z = positions.getZ( i + 1 );
let txtDis = endbuff.length();
let color = i==0? dirs[0].color : (i==2? dirs[1].color: dirs[2].color);
let angTxt = i==0? dirs[0].angTxt : (i==2? dirs[1].angTxt: dirs[2].angTxt);
let arrow = new THREE.ArrowHelper( endbuff, startbuff, txtDis+50, color, 20,10);
let text = document.createElement( 'div' );
text.className = 'txt';
text.textContent = i==0? dirs[0].name : (i==2? dirs[1].name: dirs[2].name);
text.style.color = color;
let label = new CSS2DObject( text );
let dirlen = endbuff.clone();
let dirlabel = label.clone();
endbuff.addScaledVector(offsetOther,1.2);
txtDis = endbuff.length();
endbuff.normalize();
label.translateOnAxis( endbuff , Math.ceil(txtDis/1.2));
scene.add(label, arrow);
dirlen.addScaledVector(offsetOther,2);
txtDis = dirlen.length();
dirlen.normalize();
dirlabel.translateOnAxis( dirlen , Math.ceil(txtDis/2));
labelren.push({
line: dirlabel,
angTxt,
});
}
labelren.forEach((htem,h) => {
let end = labelren[h+1]?labelren[h+1].line : labelren[0].line;
let li = addLines(htem.line.position,end.position, offsetOther, htem.angTxt,h);
scene.add( li.lineMesh);
})
window.addEventListener( 'resize', onWindowResize );
}
function addLines(v0, v3, point, txt,h) {
let angle = v0.angleTo(v3)*(180/Math.PI);
let aLen = angle * -0.4, hLen = 1;
let p0 = point.clone();
let rayLine = new THREE.Ray(p0, getVCenter(v0.clone(), p0));
let rayLine3 = new THREE.Ray(p0, getVCenter(v3.clone(), p0));
let vtop = rayLine.at(rayLine.at(1).distanceTo(p0));
let vtop3 = rayLine3.at(rayLine3.at(1).distanceTo(p0));
let v1 = getLenVcetor(v0.clone(), vtop3, aLen);
let v2 = getLenVcetor(v3.clone(), vtop3, aLen);
let curve = new THREE.CubicBezierCurve3(v0, v1, v2, v3);
let geo = new THREE.BufferGeometry().setFromPoints( curve.getPoints(50) );
let mat = new THREE.LineDashedMaterial({
color: 0x000000,
dashSize: 10,
gapSize: 6,
});
let line = new THREE.Line(geo, mat);
line.computeLineDistances();
let text2 = document.createElement( 'div' );
text2.className = 'dirtxt';
text2.textContent = txt;
let label2 = new CSS2DObject( text2 );
label2.position.copy( v2 );
if(h==0){
label2.translateY(-p0.distanceTo(v2)/2);
label2.translateX(p0.distanceTo(v3)/4)
}
if(h==1){
label2.translateZ(-p0.distanceTo(v3)/2);
label2.translateY(p0.distanceTo(v3))
}
if(h==2){
label2.translateX(-p0.distanceTo(v3)/2);
label2.translateZ(p0.distanceTo(v1)/2)
}
scene.add( label2 );
return {
curve: curve,
lineMesh: line
};
}
function getVCenter(v1, v2) {
let v = v1.add(v2);
return v.divideScalar(2);
}
function getLenVcetor(v1, v2, len) {
let v1v2Len = v1.distanceTo(v2);
return v1.lerp(v2, len / v1v2Len);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
labelRenderer.setSize( window.innerWidth, window.innerHeight );
render();
}
function animate() {
requestAnimationFrame( animate );
controls.update();
render();
}
function render() {
renderer.render( scene, camera );
labelRenderer.render( scene, camera );
}
</script>
#container{
width:1200px;
height:600px;
border:1px solid #ddd;
}