gpt4 book ai didi

javascript - Three.js Globe 中的 HTML 元素

转载 作者:行者123 更新时间:2023-11-28 18:57:26 25 4
gpt4 key购买 nike

我有一个使用 Three.js 构建的地球仪

引用:http://callumprentice.github.io/apps/globe_manipulator/index.html

我需要在特定的纬度/经度处显示 HTML div,您能告诉我如何将 div 定位在某个特定的纬度/经度吗?

我尝试过什么:我什至无法继续将 lat lon 转换为屏幕 x 和 y 坐标。

我的JS代码:

            var camera, scene, renderer, controls, root_object = 0, mesh;
var uniform_color = true, uniform_height = true, extrusion_amount = 5.0;
var helper_1, helper_2;
var radius;
init();
animate();

function _convertLatLonToVec3 (lat,lon) {
lat = lat * Math.PI / 180.0;
lon = -lon * Math.PI / 180.0;
return new THREE.Vector3(
Math.cos(lat) * Math.cos(lon), //rechts links invert
Math.sin(lat), // up down invert
Math.cos(lat) * Math.sin(lon));
}

function InfoBox( city, mesh, radius, domElement )
{
var position = _convertLatLonToVec3( city.lat, city.lng ).multiplyScalar( radius );
this.mesh = mesh;
this.mesh.position.copy( position );

this._screenVector = new THREE.Vector3(0,0,0);

this.box = document.createElement( 'div' );
this.box.innerHTML = city.name;
this.box.className = "hudLabel";

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

}

InfoBox.prototype.update = function ()
{

this._screenVector.set( 0, 0, 0 );
this.mesh.localToWorld( this._screenVector );
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();

this.box.style.left = ( posx - boundingRect.width ) + 'px';
this.box.style.top = posy + 'px';

};


function init() {
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setClearColor(0x131C1D, 1.0);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

scene = new THREE.Scene();

camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 2000);
camera.position.z = 400;
camera.position.y = 400;

var light = new THREE.DirectionalLight(0xffffff);
light.position.set(1, 0, 0);
scene.add(light);
var light2 = new THREE.DirectionalLight(0xffffff);
light2.position.set(0, 0, 1);
scene.add(light2);

radius = 300;
var segments = 128;
var rings = 128;
var geometry = new THREE.SphereGeometry(radius, segments, rings);
material_map = THREE.ImageUtils.loadTexture('textures/sea_texture.jpg');
material_map.wrapS = THREE.RepeatWrapping;
material_map.wrapT = THREE.RepeatWrapping;
material_map.repeat.set(8, 8);
material = new THREE.MeshPhongMaterial({
//map: material_map,
color: 0xFFffffff,
opacity: 0,
transparent: true
});
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

var helper_geometry = new THREE.SphereGeometry( 2, 32, 32 );
helper_1 = new THREE.Mesh( helper_geometry, new THREE.MeshNormalMaterial() );
scene.add( helper_1 )
helper_2 = new THREE.Mesh( helper_geometry, new THREE.MeshNormalMaterial() );
scene.add( helper_2 )

add_all_countries();

controls = new THREE.TrackballControls(camera, renderer.domElement);

globe_manipulator = new globe_manipulator({
dom_object: renderer.domElement,
camera: camera,
radius: radius,
on_clicked_callback: onClicked,
auto_rotate: true,
right_click_to_select: true,
start_lat: 0.0,
start_lng: 0.0,
start_distance: 900.0,
min_distance: 560.0,
max_distance: 1200.0,
mesh: mesh
});
gotoRandomCity();
window.addEventListener('resize', onWindowResize, false);

}


function onClicked(event) {

if ( event.mouse_event.button == 2 ) {
if ( event.intersects ) {
actual_latlng = "Lat: " + event.lat.toFixed(2) + " Lng: " + event.lng.toFixed(2);

var phi = (90.0 - event.lat) * Math.PI / 180.0;
var theta = (360.0 - event.lng) * Math.PI / 180.0;
var x = radius * Math.sin(phi) * Math.cos(theta);
var y = radius * Math.cos(phi);
var z = radius * Math.sin(phi) * Math.sin(theta);

helper_2.position.set( x, y, z );

}
else {
actual_latlng = "Missed";
}
}
}


function gotoRandomCity() {



var name = "Delhi";
var lat = 28.6100;
var lng = 77.2300;

var phi = (90.0 - lat) * Math.PI / 180.0;
var theta = (360.0 - lng) * Math.PI / 180.0;
var x = radius * Math.sin(phi) * Math.cos(theta);
var y = radius * Math.cos(phi);
var z = radius * Math.sin(phi) * Math.sin(theta);

helper_1.position.set( x, y, z );


city_name = name;
target_latlng = "Lat: " + lat.toFixed(2) + " Lng: " + lng.toFixed(2);
console.log(lat+" "+lng);
globe_manipulator.set_lat_lng(lat, lng);

var marker = new THREE.Mesh( new THREE.SphereGeometry( 5, 16, 16 ) );
scene.add( marker );

var city = { "name": "Hello", "lat": lat, "lng": lng };

label = new InfoBox( city, marker, radius, document.body );

}

function add_country(shape_points) {
var shape = new THREE.Shape(shape_points);
var shape_geom;
var inner_radius = 300.0;
var outer_radius = 305.0;

shape_geom = shape.extrude({
amount: outer_radius - inner_radius,
bevelEnabled: false
});

var offset = 0;
if ( ! uniform_height )
offset = Math.random() * extrusion_amount;

shape_geom.vertices.forEach(function (vert, index) {
var radius = 0.0;
if (index < shape_geom.vertices.length / 2) {
radius = inner_radius;
} else {
radius = inner_radius + extrusion_amount + offset;
}
var phi = (90.0 - vert.y) * Math.PI / 180.0;
var theta = (360.0 - vert.x) * Math.PI / 180.0;
vert.x = radius * Math.sin(phi) * Math.cos(theta);;
vert.y = radius * Math.cos(phi);;
vert.z = radius * Math.sin(phi) * Math.sin(theta);;
});
var color = new THREE.Color(0x90BAC0);
if (! uniform_color)
color.setHSL(Math.random(),0.8,0.8 );

var shape_material = new THREE.MeshPhongMaterial({
color: color,
side: THREE.DoubleSide
});
var shape_mesh = new THREE.Mesh(shape_geom, shape_material);
root_object.add(shape_mesh);
}

function add_all_countries() {

if ( root_object ) {
scene.remove(root_object);
}

root_object = new THREE.Object3D();
scene.add(root_object);

countries.features.forEach(function (country) {
if (country.geometry.coordinates.length === 1) {
var shape_points = [];
country.geometry.coordinates[0].forEach(function (points) {
shape_points.push(new THREE.Vector2(points[0], points[1]));
});
add_country(shape_points);
} else {
country.geometry.coordinates.forEach(function (coord_set) {
if (coord_set.length == 1) {
var shape_points = [];
coord_set[0].forEach(function (points) {
shape_points.push(new THREE.Vector2(points[0], points[1]));
});
add_country(shape_points);
} else {
var shape_points = [];
coord_set.forEach(function (points) {
shape_points.push(new THREE.Vector2(points[0], points[1]));
});
add_country(shape_points);
}
});
}
});
}

function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}

function animate() {



requestAnimationFrame(animate);
globe_manipulator.update();
//controls.update();
///console.log(label_html);

label.update();
renderer.render(scene, camera);


/*
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);*/
}

globe_manipulator 并没有造成问题。

最佳答案

我现在将此作为答案发布,因为它超出了评论意图。

首先,将您的纬度/经度转换为 THREE.Vector3。您可以使用此功能:

function convertLatLonToVec3(lat,lon) {
lat = lat * Math.PI / 180.0;
lon = -lon * Math.PI / 180.0;
return new THREE.Vector3(
Math.cos(lat) * Math.cos(lon),
Math.sin(lat),
Math.cos(lat) * Math.sin(lon));
};

将此 Vector3 乘以球体(地球仪)的半径即可得到位置:

var radius = 100;
var position = convertLatLonToVec3( city.lat, city.lng ).multiplyScalar( radius );

这是您在 3D 空间中的位置。

下一步从 3D 空间位置获取屏幕空间位置并更新 HTML 覆盖框位置。简而言之,它是这样的:

var screenVector = new THREE.Vector3( 0, 0, 0 );
screenVector.copy( position );
screenVector.project( camera );

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

// the html overlaybox
this.box.style.left = posx + 'px';
this.box.style.top = posy + 'px';

这需要在每次更新时完成,makc 为此劫持了 Object3D。

这是一个简单的 fiddle ,可以帮助您理解 http://jsfiddle.net/qac19w5x/

enter image description here

再次仅供引用,请参阅 makc 中的现成类:three-js-and-2d-overlays

关于javascript - Three.js Globe 中的 HTML 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33345464/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com