html中标签样式:
.tap{
position: absolute;
background-color: MidnightBlue;
background-color:rgba(0,10,40);
border-top-left-radius: 10px;
border-bottom-right-radius:10px;
opacity: 0.5;
font-size: 4px;
color: aqua;
width: 36px;
height: 44px;
padding: 1px 1px 1px;
}
js中动态添加
//txt1 txt2 txt3 为div中要显示的文本,具体样式可修改 innerHTML那一行
function addDom(txt1,txt2,txt3) {
let addDivDom = document.createElement('div');
let bodyDom = document.body;
bodyDom.insertBefore(addDivDom, bodyDom.lastChild);
addDivDom.classList = 'tap';
addDivDom.innerHTML = '<span style="color:white;font-size: 10px;padding: 5px">' + txt1 + '</span>'+'<span style="font-size: 11px;font-weight: bold">'+txt2+'</span>'+'<p style="padding: 5px;margin-top: -3px;">'+txt3+'</p>';
}
render中要实时渲染修改标签的二维坐标,代码中的position为三维坐标,即标签插入时的三维坐标
function renderLabel(){
div.style.left=transPosition(position).x + 'px';
div.style.top=transPosition(position).y + 'px';
}
//三维坐标转屏幕坐标
function transPosition (position) {
let world_vector = new THREE.Vector3(position.x, position.y, position.z);
let vector = world_vector.project(camera);
let halfWidth = window.innerWidth / 2,
halfHeight = window.innerHeight / 2;
return {
x: Math.round(vector.x * halfWidth + halfWidth),
y: Math.round(-vector.y * halfHeight + halfHeight)
};
}
具体实例1:给建筑物添加标签
效果图:
(图一标签为颜色最暗的建筑的标签,图二为最高的建筑的标签)
let build=new THREE.Group();
var loader = new THREE.VRMLLoader();
//加载一个wrl格式的模型,其他格式模型同样,自建cube等不需要自建box
loader.load( 'model/h.wrl', function ( object ) {
object.castShadow = true;
build= object.children[0].children[0];
build.castShadow = true;
object.position.x=-20;
object.position.y=0;
object.position.z=-30;
scene.add(object);
let box= creatBoundingBox(object);
build.box=box;
addDom("楼宇名称 ","h 可点击","占地面积:25541平方米",box);
CubeArray.push(box);
})
function addDom(txt1,txt2,txt3,cube) {
let addDivDom = document.createElement('div');
let bodyDom = document.body;
bodyDom.insertBefore(addDivDom, bodyDom.lastChild);
addDivDom.id=cube.uuid+"_text";
addDivDom.classList = 'tap';
addDivDom.innerHTML = '<span style="color:white;font-size: 10px;padding: 5px">' + txt1 + '</span>'+'<span style="font-size: 11px;font-weight: bold">'+txt2+'</span>'+'<p style="padding: 5px;margin-top: -3px;">'+txt3+'</p>';
divIdArray.push(addDivDom.id);
}
//渲染实时更新标签位置
function render() {
cubeLabe();
renderer.render(scene, camera);
}
//只显示最近点击的楼的标签 其他标签隐藏不显示
function cubeLabe() {
if(IsSelectedMesh==true)
{
let cube=clickmesh;
let divid=cube.uuid+"_text";
for(let i=0;i<divIdArray.length;i++) {
let id = divIdArray[i];
let div = document.getElementById(id);
if(id==divid)
{
if(div!=null&&div!=undefined){
div.style.display="";
div.style.left=interface.transPosition(cube.position).x + 'px';
let posi=new THREE.Vector3(cube.position.x,(cube.position.y)*2,cube.position.z);
div.style.top=interface.transPosition(posi).y-100 + 'px';
// let number=cube.uuid;
// div.style.zIndex=number;
}
}else {
if(div!=null&&div!=undefined){
div.style.display = "none";
}
}
}
}else {
for(let i=0;i<divIdArray.length;i++) {
let id = divIdArray[i];
let div = document.getElementById(id);
if(div!=null||div!=undefined){
div.style.display = "none";
}
}
}
}
//生成模型包围盒实体,方便标签判断位置
function creatBoundingBox(object) {
//计算包围盒长宽高
let Box=new THREE.Box3();
Box.setFromObject(object);
if ( Box.isEmpty() ) return;
let min = Box.min;
let max = Box.max;
let width=max.x-min.x;
let height=max.y-min.y;
let deepth=max.z-min.z;
// console.log(width+";"+height+";"+deepth);
//计算包围盒中心点
let centerX=(max.x+min.x)/2;
let centerY=(max.y+min.y)/2;
let centerZ=(max.z+min.z)/2;
//画一个boundingbox的cube实体
let boxGeometry=new THREE.BoxGeometry(width,height,deepth);
let boxMaterial=new THREE.MeshLambertMaterial({});
let box=new THREE.Mesh(boxGeometry,boxMaterial);
box.position.set(centerX,centerY,centerZ);
return box;
}
具体实例2 点击模型表面添加标签,标签为图片
效果图:
var fixedBoard = function () {
position:null;
div:null;
image:null
}
var fixedBoardlist=[];
//添加鼠标事件 移除鼠标事件
function ImageTag() {
addEventListener('click',addFixedBoard);// 监听窗口鼠标单击事件
$(document).keydown(function (event) {
if (event.keyCode == 27) {
removeAddBoard();
}
});
}
//固定位置的标签
function addFixedBoard() {
var windowX = event.clientX;//鼠标单击位置横坐标
var windowY = event.clientY;//鼠标单击位置纵坐标
var addDivDom = document.createElement('div');
var bodyDom = document.body;
bodyDom.insertBefore(addDivDom, bodyDom.lastChild);
// addDivDom.id=cube.uuid+"_text";
addDivDom.classList = 'tap';
var img=new Image();
// var image=document.createElement("img");
var image_src="./img/002.png";
img.src=image_src;
addDivDom.appendChild(img);
var x = (windowX / window.innerWidth) * 2 - 1;//标准设备横坐标
var y = -(windowY / window.innerHeight) * 2 + 1;//标准设备纵坐标
var standardVector = new THREE.Vector3(x, y, 0.5);//标准设备坐标
//标准设备坐标转世界坐标
var worldVector = standardVector.unproject(camera);
var ray = worldVector.sub(camera.position).normalize();
//创建射线投射器对象
var raycaster = new THREE.Raycaster(camera.position, ray);
//返回射线选中的对象
var intersects = raycaster.intersectObjects(floorChildrenGroup);
console.log(intersects);
if (intersects.length > 0) {
var point=intersects[0].point;
var board=new fixedBoard();
board.position=point;
board.div=addDivDom;
board.image=img;
fixedBoardlist.push(board);
}
}
//移除鼠标单击事件绑定
function removeAddBoard() {
removeEventListener('click',addFixedBoard);
}
//实时修改渲染时的图片位置
function imagePosition() {
for(var i=0;i<fixedBoardlist.length;i++){
var position=fixedBoardlist[i].position;
var div=fixedBoardlist[i].div;
var x=interface.transPosition(position).x;
var y=interface.transPosition(position).y;
var image=fixedBoardlist[i].image;
var width=image.width;
var height=image.height;
div.style.top=y-height+ 'px';
div.style.left=x-width/2+ 'px';
}
}
//报警标签
function Warning(Istrue) {
if(Istrue){
for(var i=0;i<fixedBoardlist.length;i++){
fixedBoardlist[i].image.src='./img/003.png';
}
var button0=document.getElementById('warn');
button0.style.display="none";
var button1=document.getElementById('cancelwarn');
button1.style.display="";
}else {
for(var i=0;i<fixedBoardlist.length;i++){
fixedBoardlist[i].image.src='./img/002.png';
}
var button0=document.getElementById('warn');
button0.style.display="";
var button1=document.getElementById('cancelwarn');
button1.style.display="none";
}
}
function render(){
renderer.render(scene, camera);
imagePosition();
}