赞
踩
效果图:
//精灵标签--标签永远面向相机
function createTxt(position,name){
var texture = new THREE.CanvasTexture(getCanvasFont());
var fontMesh = new THREE.Sprite(new THREE.SpriteMaterial({map: texture}));
// 放大
fontMesh.scale.x = 10;
fontMesh.scale.y = 5;
// 在原位置各加 2px ,避免文字与地标重叠
fontMesh.position.x = (position.x >0 ? position.x+2 : position.x-2);
fontMesh.position.y = (position.y >0 ? position.y+2 : position.y-2);
fontMesh.position.z = (position.z >0 ? position.z+2 : position.z-2);
// fontMesh.position.copy(position); //原位置
scene.add(fontMesh);
// canvas生成图片实现文字函数
function getCanvasFont() {
let w = 600;
let h = 300;
let canvas = document.createElement("canvas");
let ctx = canvas.getContext('2d');
canvas.width = w;
canvas.height = h;
//制作矩形
ctx.fillStyle = "red";
ctx.fillRect(0, 0, w, h)
//设置文字
ctx.fillStyle = "black";
ctx.font = h/3 + 'px "微软雅黑"';
ctx.textAlign = 'center';
ctx.fillText(name, w/2, h/2+20 )
return canvas;
}
}
效果图:
//贴图标签,标签与球面融为一体
function createTextCanvas(position,name) {
//用canvas生成图片
let w = 200;
let h = 100;
let canvas = document.createElement("canvas");
let ctx = canvas.getContext('2d');
canvas.width = w;
canvas.height = h;
//左右翻转
ctx.scale(-1, 1);
ctx.translate(-w, 0);
//制作矩形
ctx.fillStyle = "red";
ctx.fillRect(0, 0, w, h)
//设置文字
ctx.fillStyle = "black";
ctx.font = h/2 + 'px "微软雅黑"';
ctx.textAlign = 'center';
ctx.fillText(name, h, h/2+20);
//生成图片
let url = canvas.toDataURL('image/png');
//几何体--长方形
let geometry1 = new THREE.PlaneGeometry(6, 3);
//将图片构建到纹理中
let material1 = new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load(url),
side: THREE.DoubleSide, //两面可见
opacity: 1
});
let txtMesh = new THREE.Mesh(geometry1, material1);
txtMesh.position.copy(position);
txtMesh.lookAt(new THREE.Vector3(0, 0,0));
scene.add(txtMesh);
}
<!DOCTYPE html>
<html>
<head>
<title>Threejs实现绘制地球,地理位置标注</title>
<meta charset="UTF-8">
<script type="text/javascript" src="js/three.js"></script>
<script type="text/javascript" src="js/OrbitControls.js"></script>
<script type="text/javascript" src="js/makeTextSprite.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="dom"></div>
<script type="text/javascript">
var scene;
var camera;
var renderer;
var radius = 100; // 地球半径
var dom = document.getElementById("dom")
var areas = [{
name: "中国",
position: [116.20, 39.55]
}, {
name: "中非共和国",
position: [18.35, 4.23]
}, {
name: "智利",
position: [-70.40, -33.24]
}, {
name: "乍得",
position: [14.59, 12.10]
}, {
name: "赞比亚",
position: [28.16, -15.28]
}, {
name: "越南",
position: [105.55, 21.05]
}, {
name: "约旦",
position: [35.52, 31.57]
}, {
name: "维尔京群岛",
position: [-64.37, 18.27]
}, {
name: "英国",
position: [-0.05, 51.36]
}];
function init() {
// 创建一个场景,它将包含我们所有的元素,如物体,相机和灯光。
scene = new THREE.Scene();
// 环境光(颜色,亮度)
var ambientLight = new THREE.AmbientLight("#ffffff", 1.2);
scene.add(ambientLight);
// 创建一个摄像机,它定义了我们正在看的地方
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
// 将摄像机对准场景的中心
camera.position.set(0, 100, -400);
camera.lookAt(scene.position);
// 创建一个渲染器并设置大小,WebGLRenderer将会使用电脑显卡来渲染场景
renderer = new THREE.WebGLRenderer({
antialias: true, //是否执行抗锯齿
logarithmicDepthBuffer: false, //如果要在单个场景中处理巨大的比例差异,就有必要使用。此处要用false,否则文字标签不显示
});
renderer.setSize(window.innerWidth, window.innerHeight);
// renderer.setClearColor(0x000000, 1); //设置背景颜色
// 设置背景图
var texture = new THREE.TextureLoader().load('imges/back.jpg');
scene.background = texture;
// 显示坐标轴
var axes = new THREE.AxisHelper(radius);
scene.add(axes);
//轨道控制器
var controls = new THREE.OrbitControls(camera);
controls.minPolarAngle = 0;
controls.maxPolarAngle = Math.PI / 1; // 上下翻转范围 0-max度
controls.minDistance = 120; // 设置移动的最短距离(默认为零)
controls.maxDistance = 1000; // 设置移动的最长距离(默认为无穷)
controls.update(); // 照相机转动时,必须更新该控制器
// 将呈现器的输出添加到HTML元素
document.getElementById("dom").appendChild(renderer.domElement);
// 运行函数
createEarth();
createAreaPoint();
renderScene();
// 创建地球 半径100
function createEarth() {
var earthGeo = new THREE.SphereGeometry(radius, 50, 50);
var earthMater = new THREE.MeshPhongMaterial({
map: new THREE.TextureLoader().load('imges/earth.jpg'),
//透明球体
// transparent: true,
// depthWrite: false,
// side: THREE.DoubleSide,
// blending: THREE.AdditiveBlending,
// opacity: 0.8,
// color: 0x03d98e
});
var earthMesh = new THREE.Mesh(earthGeo, earthMater);
scene.add(earthMesh);
}
// 创建地标
function createAreaPoint() {
// 循环创建地标,文字标签
for (let i = 0, length = areas.length; i < length; i++) {
const name = areas[i].name
const position = createPosition(areas[i].position)
createHexagon(position); // 地标函数
createTxt(position,name); // 精灵标签函数
// createTextCanvas(position,name) // 贴图标签函数
}
}
// 经纬度转坐标
function createPosition(lnglat) {
let spherical = new THREE.Spherical
spherical.radius = radius;
const lng = lnglat[0]
const lat = lnglat[1]
const theta = (lng + 90) * (Math.PI / 180)
const phi = (90 - lat) * (Math.PI / 180)
spherical.phi = phi; // phi是方位面(水平面)内的角度,范围0~360度
spherical.theta = theta; // theta是俯仰面(竖直面)内的角度,范围0~180度
let position = new THREE.Vector3()
position.setFromSpherical(spherical)
return position
}
// 创建地标标记
function createHexagon(position) {
var hexagon = new THREE.Object3D()
let hexagonLine = new THREE.CircleGeometry(2, 6)
let hexagonPlane = new THREE.CircleGeometry(1, 6)
let vertices = hexagonLine.vertices
vertices.shift() // 第一个节点是中心点
let material = new THREE.MeshBasicMaterial({
color: 0xffff00,
side: THREE.DoubleSide, //让材质单面或者双面显示,前面FrontSide ,背面:BackSide ,双面:DoubleSide
opacity: 0.5
})
let circleLine = new THREE.LineLoop(hexagonLine, material)
let circlePlane = new THREE.Mesh(hexagonPlane, material)
circleLine.position.copy(position)
circlePlane.position.copy(position)
circlePlane.lookAt(new THREE.Vector3(0, 0, 0))
circleLine.lookAt(new THREE.Vector3(0, 0, 0))
hexagon.add(circleLine)
hexagon.add(circlePlane)
scene.add(hexagon);
}
//贴图标签,标签与球面融为一体
function createTextCanvas(position,name) {
//用canvas生成图片
let w = 200;
let h = 100;
let canvas = document.createElement("canvas");
let ctx = canvas.getContext('2d');
canvas.width = w;
canvas.height = h;
//左右翻转
ctx.scale(-1, 1);
ctx.translate(-w, 0);
//制作矩形
ctx.fillStyle = "red";
ctx.fillRect(0, 0, w, h)
//设置文字
ctx.fillStyle = "black";
ctx.font = h/2 + 'px "微软雅黑"';
ctx.textAlign = 'center';
ctx.fillText(name, h, h/2+20);
//生成图片
let url = canvas.toDataURL('image/png');
//几何体--长方形
let geometry1 = new THREE.PlaneGeometry(6, 3);
//将图片构建到纹理中
let material1 = new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load(url),
side: THREE.DoubleSide, //两面可见
opacity: 1
});
let txtMesh = new THREE.Mesh(geometry1, material1);
txtMesh.position.copy(position);
txtMesh.lookAt(new THREE.Vector3(0, 0,0));
scene.add(txtMesh);
}
//精灵标签--标签永远面向相机
function createTxt(position,name){
var texture = new THREE.CanvasTexture(getCanvasFont());
var fontMesh = new THREE.Sprite(new THREE.SpriteMaterial({map: texture}));
// 放大
fontMesh.scale.x = 10;
fontMesh.scale.y = 5;
// 在原位置各加 2px ,避免文字与地标重叠
fontMesh.position.x = (position.x >0 ? position.x+2 : position.x-2);
fontMesh.position.y = (position.y >0 ? position.y+2 : position.y-2);
fontMesh.position.z = (position.z >0 ? position.z+2 : position.z-2);
// fontMesh.position.copy(position); //原位置
scene.add(fontMesh);
// canvas生成图片实现文字函数
function getCanvasFont() {
let w = 600;
let h = 300;
let canvas = document.createElement("canvas");
let ctx = canvas.getContext('2d');
canvas.width = w;
canvas.height = h;
//制作矩形
ctx.fillStyle = "red";
ctx.fillRect(0, 0, w, h)
//设置文字
ctx.fillStyle = "black";
ctx.font = h/3 + 'px "微软雅黑"';
ctx.textAlign = 'center';
ctx.fillText(name, w/2, h/2+20 )
return canvas;
}
}
function renderScene() {
requestAnimationFrame(renderScene); //循环调用renderScene函数
renderer.render(scene, camera);
}
}
// 随着窗体的变化修改场景大小
function onResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// 监听窗体调整大小事件
window.addEventListener('resize', onResize, false);
/* 页面绘制完后加载,避免页面闪动 */
window.onload = function() {
init();
}
</script>
</body>
</html>
参考文章:http://zuoben.top/#1-12
地球高清全景图: https://www.aliyundrive.com/s/C2kStb7B41c
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。