This commit is contained in:
99
js/globe.js
99
js/globe.js
@@ -65,6 +65,31 @@
|
||||
{ name: "San Francisco", lat: 37.8, lng: -122.4 }
|
||||
];
|
||||
|
||||
// 基于节点构造“飞行轨迹”连接数据(startLat/startLng -> endLat/endLng)
|
||||
function buildArcsFromNodes(list) {
|
||||
var arcs = [];
|
||||
if (!Array.isArray(list) || list.length < 2) {
|
||||
return arcs;
|
||||
}
|
||||
// 简单策略:每个节点连接到后面第 step 个节点,形成环状主干网络
|
||||
var step = Math.max(1, Math.floor(list.length / 3));
|
||||
list.forEach(function (src, idx) {
|
||||
var dst = list[(idx + step) % list.length];
|
||||
if (!dst || (dst.lat === src.lat && dst.lng === src.lng)) {
|
||||
return;
|
||||
}
|
||||
arcs.push({
|
||||
startLat: src.lat,
|
||||
startLng: src.lng,
|
||||
endLat: dst.lat,
|
||||
endLng: dst.lng,
|
||||
// 统一使用偏青色的轨迹,贴合云服务器 / CDN 的科技感
|
||||
color: "#38BDF8",
|
||||
});
|
||||
});
|
||||
return arcs;
|
||||
}
|
||||
|
||||
// three-globe 实例:使用空心陆地多边形(hollow globe 风格)
|
||||
var globe = new ThreeGlobe({
|
||||
waitForGlobeReady: true,
|
||||
@@ -79,8 +104,40 @@
|
||||
|
||||
scene.add(globe);
|
||||
|
||||
// 存放自定义“闪烁节点” mesh,便于在动画循环中更新
|
||||
var nodeGlows = [];
|
||||
// 构造并应用“节点连接 + 飞行轨迹”效果
|
||||
var arcs = buildArcsFromNodes(nodes);
|
||||
if (typeof globe.arcsData === "function" && arcs.length) {
|
||||
globe.arcsData(arcs);
|
||||
if (typeof globe.arcColor === "function") {
|
||||
globe.arcColor(function (d) {
|
||||
return d.color || "#38BDF8";
|
||||
});
|
||||
}
|
||||
if (typeof globe.arcAltitude === "function") {
|
||||
globe.arcAltitude(0.2);
|
||||
}
|
||||
if (typeof globe.arcStroke === "function") {
|
||||
globe.arcStroke(0.7);
|
||||
}
|
||||
// 使用虚线 + 动画时间制造“飞行”感
|
||||
if (typeof globe.arcDashLength === "function") {
|
||||
globe.arcDashLength(0.35);
|
||||
}
|
||||
if (typeof globe.arcDashGap === "function") {
|
||||
globe.arcDashGap(0.8);
|
||||
}
|
||||
if (typeof globe.arcDashInitialGap === "function") {
|
||||
globe.arcDashInitialGap(function () {
|
||||
return Math.random();
|
||||
});
|
||||
}
|
||||
if (typeof globe.arcDashAnimateTime === "function") {
|
||||
globe.arcDashAnimateTime(function () {
|
||||
// 4~7 秒一圈,避免所有轨迹节奏完全一致
|
||||
return 4000 + Math.random() * 3000;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 告诉 three-globe 当前渲染器的实际尺寸,避免默认按全窗口大小计算导致比例失真
|
||||
if (typeof globe.rendererSize === "function") {
|
||||
@@ -95,6 +152,15 @@
|
||||
var dist = r * 3.2;
|
||||
camera.position.set(0, 0.2, dist);
|
||||
camera.lookAt(0, 0, 0);
|
||||
|
||||
// 在节点位置放置小型静态“节点点”,替代原来的绿色闪烁效果
|
||||
var nodeGeom = new THREE.SphereGeometry(r * 0.02, 16, 16);
|
||||
var nodeMat = new THREE.MeshBasicMaterial({
|
||||
color: "#38BDF8",
|
||||
transparent: true,
|
||||
opacity: 0.9,
|
||||
});
|
||||
|
||||
// 通知 three-globe 当前视角,用于部分图层的内部计算
|
||||
if (typeof globe.setPointOfView === "function") {
|
||||
globe.setPointOfView(camera);
|
||||
@@ -102,7 +168,7 @@
|
||||
|
||||
// 使用 globe 的工具方法,将经纬度转换为球面上的 3D 坐标
|
||||
var hasGetCoords = typeof globe.getCoords === "function";
|
||||
nodes.forEach(function (n, idx) {
|
||||
nodes.forEach(function (n) {
|
||||
var pos;
|
||||
if (hasGetCoords) {
|
||||
// altitude 略高于球面,避免被多边形遮挡
|
||||
@@ -119,22 +185,9 @@
|
||||
};
|
||||
}
|
||||
|
||||
var glowGeom = new THREE.SphereGeometry(r * 0.03, 16, 16);
|
||||
var glowMat = new THREE.MeshBasicMaterial({
|
||||
// 绿色闪烁点,和蓝色陆地形成冷暖对比
|
||||
color: "#22C55E",
|
||||
transparent: true,
|
||||
opacity: 0.7
|
||||
});
|
||||
var glowMesh = new THREE.Mesh(glowGeom, glowMat);
|
||||
glowMesh.position.set(pos.x, pos.y, pos.z);
|
||||
globe.add(glowMesh);
|
||||
|
||||
nodeGlows.push({
|
||||
mesh: glowMesh,
|
||||
// 随机相位,让节点闪烁不同步
|
||||
phase: Math.random() * Math.PI * 2 + idx
|
||||
});
|
||||
var nodeMesh = new THREE.Mesh(nodeGeom, nodeMat);
|
||||
nodeMesh.position.set(pos.x, pos.y, pos.z);
|
||||
globe.add(nodeMesh);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -219,14 +272,6 @@
|
||||
// 地球自转
|
||||
globe.rotation.y += delta * 0.25;
|
||||
|
||||
// 节点“呼吸式”闪烁
|
||||
var t = now / 1000;
|
||||
nodeGlows.forEach(function (n) {
|
||||
var s = 0.7 + 0.3 * Math.sin(t * 3 + n.phase);
|
||||
n.mesh.scale.set(s, s, s);
|
||||
n.mesh.material.opacity = 0.4 + 0.4 * Math.sin(t * 3 + n.phase);
|
||||
});
|
||||
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user