diff --git a/css/index.css b/css/index.css
index 5044f8b..6ba6952 100644
--- a/css/index.css
+++ b/css/index.css
@@ -68,6 +68,33 @@
pointer-events: auto;
}
+/* 3D 地球容器:位于轮播图偏中右位置 */
+.banner-globe {
+ position: absolute;
+ top: 50%;
+ right: 8%; /* 根据视觉调节,让地球更靠中间一点 */
+ transform: translateY(-50%);
+ width: 420px;
+ height: 420px;
+ pointer-events: none; /* 不影响轮播图滑动与点击 */
+}
+
+/* 中等屏幕下缩小地球,避免挡住文案 */
+@media (max-width: 1400px) {
+ .banner-globe {
+ right: 4%;
+ width: 360px;
+ height: 360px;
+ }
+}
+
+/* 小屏幕(如窄笔记本)下隐藏 3D 地球,保持可用性 */
+@media (max-width: 1100px) {
+ .banner-globe {
+ display: none;
+ }
+}
+
.banner .banner-s {
box-shadow: 0px 0px 16px rgba(52, 52, 52, 0.16);
border-radius: 3px;
diff --git a/index.html b/index.html
index 6e25044..38208a5 100644
--- a/index.html
+++ b/index.html
@@ -3,8 +3,13 @@
-
-
+
+
+
+
+
+
+
@@ -32,6 +37,8 @@
+
+
diff --git a/js/globe.js b/js/globe.js
new file mode 100644
index 0000000..5ed93bf
--- /dev/null
+++ b/js/globe.js
@@ -0,0 +1,184 @@
+// 3D 地球效果(首页 banner 右侧)
+// 依赖:Three.js(全局 THREE 对象),脚本路径建议:/web/BlackFruit-web/vender/three/three.min.js
+
+(function () {
+ function initGlobe() {
+ var container = document.getElementById("bannerGlobe");
+ if (!container) return;
+ if (typeof THREE === "undefined") {
+ // Three.js 未加载时直接跳过,不影响其它功能
+ return;
+ }
+
+ var width = container.clientWidth || 400;
+ var height = container.clientHeight || 400;
+
+ var scene = new THREE.Scene();
+
+ var camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000);
+ var radius = 1.2;
+ camera.position.set(0, 0, radius * 3.2);
+ camera.lookAt(0, 0, 0);
+
+ var renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
+ renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2));
+ renderer.setSize(width, height);
+ renderer.setClearColor(0x000000, 0); // 透明背景,融入页面
+ container.appendChild(renderer.domElement);
+
+ // 光照:柔和的环境光 + 方向光
+ scene.add(new THREE.AmbientLight(0xffffff, 0.5));
+ var dirLight = new THREE.DirectionalLight(0xffffff, 0.9);
+ dirLight.position.set(5, 3, 5);
+ scene.add(dirLight);
+
+ var globeGroup = new THREE.Group();
+ scene.add(globeGroup);
+
+ // 地球球体
+ var earthGeometry = new THREE.SphereGeometry(radius, 64, 64);
+
+ // 纯色高光材质,若后续有贴图可替换为 MeshPhongMaterial + map
+ var earthMaterial = new THREE.MeshPhongMaterial({
+ color: 0x163a5f,
+ emissive: 0x061727,
+ shininess: 35,
+ specular: 0x3aaefc,
+ });
+
+ var earthMesh = new THREE.Mesh(earthGeometry, earthMaterial);
+ globeGroup.add(earthMesh);
+
+ // 大气层发光效果
+ var atmosphereGeometry = new THREE.SphereGeometry(radius * 1.06, 64, 64);
+ var atmosphereMaterial = new THREE.MeshBasicMaterial({
+ color: 0x2b9fff,
+ transparent: true,
+ opacity: 0.25,
+ side: THREE.BackSide,
+ });
+ var atmosphereMesh = new THREE.Mesh(
+ atmosphereGeometry,
+ atmosphereMaterial
+ );
+ globeGroup.add(atmosphereMesh);
+
+ // 将经纬度转换为球面坐标
+ function latLngToVector3(lat, lng, r) {
+ var phi = (90 - lat) * (Math.PI / 180);
+ var theta = (lng + 180) * (Math.PI / 180);
+ var x = -r * Math.sin(phi) * Math.cos(theta);
+ var z = r * Math.sin(phi) * Math.sin(theta);
+ var y = r * Math.cos(phi);
+ return new THREE.Vector3(x, y, z);
+ }
+
+ // 一些示例节点(可以根据业务改为真实机房经纬度)
+ var nodeConfigs = [
+ { lat: 39.9, lng: 116.4 }, // 北京
+ { lat: 31.2, lng: 121.5 }, // 上海
+ { lat: 22.5, lng: 114.1 }, // 香港
+ { lat: 1.3, lng: 103.8 }, // 新加坡
+ { lat: 37.8, lng: -122.4 }, // 旧金山
+ { lat: 52.5, lng: 13.4 }, // 柏林
+ { lat: 35.7, lng: 139.7 }, // 东京
+ ];
+
+ var nodeGroup = new THREE.Group();
+ globeGroup.add(nodeGroup);
+
+ var nodeMaterial = new THREE.MeshBasicMaterial({
+ color: 0x5ad8ff,
+ });
+
+ var nodes = [];
+ var nodeRadius = radius * 0.03;
+ nodeConfigs.forEach(function (cfg, index) {
+ var pos = latLngToVector3(cfg.lat, cfg.lng, radius * 1.02);
+ var geom = new THREE.SphereGeometry(nodeRadius, 16, 16);
+ var mesh = new THREE.Mesh(geom, nodeMaterial);
+ mesh.position.copy(pos);
+ nodeGroup.add(mesh);
+
+ nodes.push({
+ mesh: mesh,
+ baseScale: 1,
+ phase: Math.random() * Math.PI * 2 + index,
+ });
+ });
+
+ // 通过 Points 实现星空点阵背景
+ var starGeometry = new THREE.BufferGeometry();
+ var starCount = 600;
+ var starPositions = new Float32Array(starCount * 3);
+ for (var i = 0; i < starCount; i++) {
+ var sr = radius * 4 + Math.random() * radius * 2;
+ var theta = Math.random() * Math.PI * 2;
+ var phi = Math.acos(2 * Math.random() - 1);
+ var sx = sr * Math.sin(phi) * Math.cos(theta);
+ var sy = sr * Math.sin(phi) * Math.sin(theta);
+ var sz = sr * Math.cos(phi);
+ starPositions[i * 3] = sx;
+ starPositions[i * 3 + 1] = sy;
+ starPositions[i * 3 + 2] = sz;
+ }
+ starGeometry.setAttribute(
+ "position",
+ new THREE.BufferAttribute(starPositions, 3)
+ );
+ var starMaterial = new THREE.PointsMaterial({
+ color: 0x3f76ff,
+ size: 0.02,
+ transparent: true,
+ opacity: 0.8,
+ });
+ var stars = new THREE.Points(starGeometry, starMaterial);
+ scene.add(stars);
+
+ // 自适应窗口大小
+ function onResize() {
+ if (!container) return;
+ var w = container.clientWidth || width;
+ var h = container.clientHeight || height;
+ camera.aspect = w / h;
+ camera.updateProjectionMatrix();
+ renderer.setSize(w, h);
+ }
+ window.addEventListener("resize", onResize);
+
+ // 动画循环
+ var lastTime = performance.now();
+
+ function animate() {
+ requestAnimationFrame(animate);
+
+ var now = performance.now();
+ var delta = (now - lastTime) / 1000;
+ lastTime = now;
+
+ // 地球缓慢自转
+ globeGroup.rotation.y += delta * 0.25;
+
+ // 星辰慢速旋转,增强空间感
+ stars.rotation.y -= delta * 0.05;
+
+ // 节点呼吸效果
+ var t = now / 1000;
+ nodes.forEach(function (n) {
+ var s = n.baseScale * (1 + 0.6 * Math.sin(t * 2.5 + n.phase));
+ n.mesh.scale.set(s, s, s);
+ });
+
+ renderer.render(scene, camera);
+ }
+
+ animate();
+ }
+
+ if (document.readyState === "loading") {
+ document.addEventListener("DOMContentLoaded", initGlobe);
+ } else {
+ initGlobe();
+ }
+})();
+