2016-09-27 120 views
0

我将纹理图像映射到球体并将标签附加到图像上,但某些标签重叠,我想要分隔标签而不更改“lon”和“lat”的值”。我需要知道如何分离标签或如何重新定位标签。并且我也上传了图片(链接)。而且我还上传了完整的代码。 请帮我解决这个问题。在这个程序中使用使用JavaScript防止标签重叠

image link

CSS代码

div.spritelabel { 
position:absolute; 
top:0px; 
left:0px; 
color:#0000FF; 
font-family: 'Trebuchet MS', sans-serif; 
font-size:15px; 
font-weight:normal; 
line-height:15px; 
text-align: left; 
padding:5px; 

-webkit-box-shadow: 0px 4px 8px -3px rgba(0,0,0,0.75); 
-moz-box-shadow: 0px 4px 8px -3px rgba(0,0,0,0.75); 
box-shadow: 0px 4px 8px -5px rgba(0,0,0,0.75); 
background:rgba(255, 255, 255, 0.8); 
} 
a:link {color: brown; background-color: transparent; text-decoration: none;} 
a:visited{color: green; background-color: transparent; text-decoration: none;} 
a:hover{color: red; background-color: transparent; text-decoration: underline;} 
a:active {color: yellow; background-color: transparent; text-decoration: underline;} 

JavaScript代码

function createsphere() 
{ 
var spriteboxes = []; 
var sprite,controls,scene,camera,renderer; 
var spritearray = []; 
spritearray[0] = {"name": "North", "lat":0, "lon": 10}; 
spritearray[1] = {"name": "south", "lat":0, "lon": 20}; 
spritearray[2] = {"name": "East", "lat":0, "lon": 30}; 
spritearray[3] = {"name": "west", "lat":0, "lon": 40}; 
spritearray[4] = {"name": "North-west", "lat":0, "lon": 45}; 
spritearray[5] = {"name": "North-east", "lat":0, "lon": 47}; 
spritearray[6] = {"name": "south-east", "lat":0, "lon": 50}; 
function convertlatlonToVec3(lat, lon) 
{ 
    lat = lat * Math.PI/180.0; 
    lon = -lon * Math.PI /180.0; 
    return new THREE.Vector3(
     Math.cos(lat)* Math.sin(lon), 
     Math.sin(lat)* Math.sin(lon), 
     Math.cos(lat)); 

} 

function labelBox(Ncardinal, radius, domElement) 
{ 
    this.screenVector = new THREE.Vector3(0, 0, 0); 
    this.position = convertlatlonToVec3(Ncardinal.lat,Ncardinal.lon).multiplyScalar(radius); 
    this.box = document.createElement('div'); 
    a = document.createElement('a'); 
    a.innerHTML = Ncardinal.name; 
    a.href ='http://www.google.de'; 
    this.box.className = "spritelabel"; 
    this.box.appendChild(a); 

    this.domElement = domElement; 
    this.domElement.appendChild(this.box); 
} 

labelBox.prototype.update = function() 
{ 
this.screenVector.copy(this.position); 
this.screenVector.project(camera); 

var posx = Math.round((this.screenVector.x + 1)* this.domElement.offsetWidth/2); 
var posy = Math.round((1 - this.screenVector.y)* this.domElement.offsetHeight/2); 

var boundingRect = this.box.getBoundingClientRect(); 

//update the box overlays position 
this.box.style.left = (posx - boundingRect.width) + 'px'; 
this.box.style.top = posy + 'px'; 



}; 





function init() 
     { 
      scene = new THREE.Scene(); 
      camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000); 
      camera.position.y = 1; 
      camera.position.z = 5; 

      var width = window.innerWidth; 
      var height = window.innerHeight; 
      renderer = new THREE.WebGLRenderer({antialias:true}); 
      renderer.setSize(width, height); 
      document.body.appendChild(renderer.domElement); 
      var radius = 2.5; 
      var spheregeometry = new THREE.SphereGeometry(radius, 20, 20, 0, -6.283, 1, 1); 
      var texture = THREE.ImageUtils.loadTexture ('Sample Images/rbi00000083.jpg'); 
      texture.minFilter = THREE.NearestFilter; 
      var spherematerial = new THREE.MeshBasicMaterial({map: texture}); 
      var sphere = new THREE.Mesh(spheregeometry, spherematerial); 

      scene.add(sphere); 
      scene.add(camera); 
      scene.autoUpdate = true; 

      controls = new THREE.OrbitControls(camera, renderer.domElement); 
      controls.minPolarAngle = Math.PI/4; 
      controls.maxPolarAngle = 3*Math.PI/4; 

      for(var i = 0; i< spritearray.length;i++) 
      { 
       var Ncardinal = spritearray[i]; 
       sprite = new labelBox(Ncardinal, radius, document.body); 
       //this.marker = new THREE.Mesh(new THREE.SphereGeometry(0.05, 30, 30)); 
       //this.marker.position.copy(sprite.position); 
       //scene.add(marker); 
       spriteboxes.push(sprite); 
      } 

      //var Ncardinal = {"name": "North", "lat":0, "lon": 10}; 
      //sprite = new labelBox(Ncardinal, radius, document.body); 


     } 
    function animate() { 

    spriteboxes.forEach(function(e) { e.update()}); 
    sprite.update(); 
    requestAnimationFrame(animate); 
    controls.update(); 
    renderer.render(scene, camera); 
      } 
init(); 
animate(); 
} 
+2

可能重复[如何避免在javacript中重叠标签?](http://stackoverflow.com/questions/39590214/how-to-avoid-labels-overlapping-in-javacript) – 2pha

+0

@ lakers1234您应该考虑删除那个问题大部分是相同的。 –

回答

0

由于您的标签都没有实际的3D对象,这个问题确实已经无关3D 。你需要做的是这个(这是一个朴素的算法,可以为大量标签等进行优化):

  • 1.)找出每个标签的确切标签尺寸,存储它们某处(使用element.offsetWidth/Height
  • 2.)计算每个标签“锚位”,即是屏幕位置
  • 3.)使用以下算法将所有标签:
    • 一个)计算如果放置在锚定位置(按Box,即顶部/左侧,底部),则由该标签占据的区域您可以使用THREE.Box2-类来存储该信息)
    • b)测试已经放置在屏幕上的所有框的交叉点(即, box.intersectsBox(otherBox))。 c)如果没有十字路口,我们有一个放置这个方块,并可以继续下一个方块
    • d)如果有交集,找到一个放置标签的地方,我简单地再根据标签的相对位置再次尝试一些像素向上/向下/向左/向右,如果在多次尝试后找不到经过放置的位置,请务必中止(并简单地跳过标签) 。

它不会总是能够找到一个地方,每一个标签,因此是很有意义的优先级开始,将其插入到命令他们。