- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个使用 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/
再次仅供引用,请参阅 makc 中的现成类:three-js-and-2d-overlays
关于javascript - Three.js Globe 中的 HTML 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33345464/
我需要制作一个像这样的 WebGL Globe: https://trends.google.com/trends/zeitgeist/2013/globe#frame=314 我已经开始使用这个例子
我使用 GADM 数据绘制了俄罗斯地区的 map : setwd("~/Desktop/Master thesis/") library(sp) library(RColorBrewer) libra
我已经能够关注 source code让我的 WebGL 地球像 the example 一样工作.我正在尝试自定义这个 Globe。我有不止一项指标需要在全局范围内展示。例如我不想只显示地球上的整个
经过长时间的搜索,我发现没有选项可以自定义标记图标。我现在尝试用两种不同类型绘制我的标记。我需要通过使用两个单独的图标来清楚地可视化它,是否有任何选项可以在 Globe 中设置自定义标记图标。更快的响
我一直在努力让 Web GL Globe ( http://code.google.com/p/webgl-globe) 正常工作。我从 Google 代码页下载源代码并将所有文件解压缩到一个文件夹中
我正在玩 WebGL Globe ( http://globe.chromeexperiments.com/ ),并希望能够用新数据“刷新”它,然后将其设置为新状态的动画。库中提供的示例没有帮助,因为
我正在开发 D3 Globe 的实现。我试图在用户单击按钮时添加到地球的路径,但事实证明这并不成功。如果我一次添加所有路径,则没有问题,但如果我尝试在触发事件后添加它们,则会失败。我的jsfiddle
我在我的程序中生成了一系列 png 图像,我计划获取的文件通过一些工具传递,将它们转换为视频文件。我正在按照我想要的正确顺序一个一个地生成文件。我想以这样的方式命名它们,以便后续的视频转换工具将在 s
如果您在 NSString 中包含 Unicode 字符,它们中的很多将采用该文本的颜色集 - 它们只是该字体的常规字形,因此它们的显示方式与其他任何字符一样特点。但是有一些 Unicode 字符是彩
我想在 planetaryJS 中添加两个功能地球仪 我想提高行星 JS 创建的地球仪的缩放速度 我怎样才能像正在生成的那样生成多个 ping here .我知道它需要一组经度和纬度,但我做不到即使是
我正在开发 WhirlyGlobe 组件测试器应用程序(mousebird 团队在 ios 中开发的地球应用程序的伟大框架)并尝试创建纬度和经度。我使用以下方法在地球上创建了经度:- (void)ad
我可以使用 Three.js 渲染 3D 地球并为其旋转设置动画,方法是使用以下链接中的教程将世界地图图像纹理添加到球体上。我打算让全局的国家都可以点击。即,每当用户单击任何国家/地区时,该国家/地区
我需要在我的网页中放置一个 3d 地球仪,我最近看到了新的谷歌地图的地球仪,这太棒了! 您可以在以下位置找到它:https://www.google.com/maps/@24.0333789,-47.
我正在尝试实现 Mike Bostock 的旋转地球仪的一个版本并覆盖国家/地区标签。这已在这里成功实现:http://bl.ocks.org/dwtkns/4686432 不幸的是,我无法隐藏应该落
你可以在给定的地球旋转链接中看到 https://codepen.io/Designer12/pen/pXxKEQ 在那里,你可以看到太多垂直和水平的蓝线,我只需要两三条线... 从脚本中,我从 中删
我们都知道http://www.chromeexperiments.com/globe/ WebGL 实验,我真的对他们在那里做了什么很感兴趣。 他们在那里所做的是根据 GPS(JSON 格式)信息在
对于我的论文项目,我使用 DataArts WebGL Globe 来开发一个网页,该网页将在触摸显示器上的展览中使用。作为监视器触摸,我需要使地球可点击以选择单个国家并打开弹出窗口并突出显示选定的国
我有一个使用 Three.js 构建的地球仪 引用:http://callumprentice.github.io/apps/globe_manipulator/index.html 我需要在特定的纬
如果这是重复的,我深表歉意(环顾四周,但我似乎找不到答案)。 假设您要将命令行属性传递给 Java 程序。例如。 -Djava.library.path=/usr/lib/jvm/java-awsom
我正试图在 python 中弄清楚如何使用 basemap 来制作这样的图: 关注左上角的图,这是每个 bin 中密度的二维直方图,图形地球覆盖在中心。 我遇到的一个大问题是, basemap 似乎不
我是一名优秀的程序员,十分优秀!