// 时间段 var curTime = Date.parse(new Date())/1000; var depTime = curTime - 30*60; // 轨迹线质 var trackMaterial = new THREE.LineBasicMaterial({color : 0x1B94B1}); // 绘制历史轨迹 function drawHistoryTrack(anum) { socket.emit("fullPath", anum, depTime, curTime, function(status, data){ if(status) { var dLength = data.length; if(dLength>=2) { var trackCoordArr = []; for(var i=0; i<dLength; i++) { if(data[i].lng && data[i].alt) { trackCoordArr.push({lng: data[i].lng, lat: data[i].lat}); } } var tcaLength = trackCoordArr.length; if(tcaLength>=2) { var tcaHalfLength = Math.ceil(tcaLength/2), vertexArr = []; // 这里只取了三个点(起点、中点、终点) var p1 = getPosition(trackCoordArr[0].lng, trackCoordArr[0].lat, 0), p2 = getPosition(trackCoordArr[tcaHalfLength].lng, trackCoordArr[tcaHalfLength].lat, tcaLength*0.01), p3 = getPosition(trackCoordArr[tcaLength-1].lng, trackCoordArr[tcaLength-1].lat, 0); var trackCurve = new THREE.CatmullRomCurve3([ new THREE.Vector3(p1.x, p1.y, p1.z), new THREE.Vector3(p2.x, p2.y, p2.z), new THREE.Vector3(p3.x, p3.y, p3.z) ]); var trackGeometry = new THREE.Geometry(), verticesArr = trackCurve.getPoints(tcaLength); trackGeometry.vertices = verticesArr; var trackLine = new THREE.Line(trackGeometry, trackMaterial); group.add(trackLine); // 动画点 addLightPoint(p1, tcaLength, verticesArr); } } } }); }
如果要绘制所有点,且头尾是在球面上的曲线,则需要两次循环
var tcaRemainLength = tcaLength-tcaHalfLength for(var j=0; j<tcaHalfLength; j++) { // 前一半 var p1 = getPosition(trackCoordArr[j].lng, trackCoordArr[j].lat, j*0.05); vertexArr.push(new THREE.Vector3(p1.x, p1.y, p1.z)); } for(var k=tcaRemainLength; k>0; k--) { // 后一半 var p2 = getPosition(trackCoordArr[tcaLength-k].lng, trackCoordArr[tcaLength-k].lat, k*0.05); vertexArr.push(new THREE.Vector3(p2.x, p2.y, p2.z)); } var trackCurve = new THREE.CatmullRomCurve3(vertexArr);
这个部分看看就行了。。
光点动画
// 点动画 var pointGeometry = new THREE.SphereGeometry(0.2, 20, 20); var pointMaterial = new THREE.MeshBasicMaterial({color: 0x40E0D0}); function addLightPoint(pos, coordsNum ,verArr) { var pointMesh = new THREE.Mesh(pointGeometry, pointMaterial); pointMesh.position.set(pos.x, pos.y, pos.z); group.add(pointMesh); var index = 0; function pointAnimate() { index++; if(index>coordsNum) { index = 0; } pointMesh.position.set(verArr[index].x, verArr[index].y, verArr[index].z); requestAnimationFrame(pointAnimate); } pointAnimate(); }
这个点使用的是sphere,,当然也可以用顶点来实现,如下
var geometry = new THREE.Geometry(); geometry.vertices.push(new THREE.Vector3(0, 0, 0)) geometry.colors.push(new THREE.Color(0xffffff)); var material = new THREE.PointsMaterial({size: 1, vertexColors: THREE.VertexColors, opacity: 0.75, sizeAttenuation: true, transparent: true}); var point = new THREE.Points(geometry, material); point.position.set(x, y, z); group.add(point);
另外不想用光点动画的话,也可以用线动画,实现原理是不断更新顶点坐标,如下
var curveGeometry = new THREE.Geometry(); var curveData = new THREE.CatmullRomCurve3(verArr.slice(0, 10)); curveGeometry.vertices = curveData.getPoints(10); var curveMaterial = new THREE.LineBasicMaterial({color: 0x40E0D0}); var curveLine = new THREE.Line(curveGeometry, curveMaterial); group.add(curveLine); var index = 0; function lineAnimate() { index++; if(index>coordsNum-10) { index = 0; } var offsetData = verArr.slice(index, 10+index); if(offsetData.length > 0) { curveData = new THREE.CatmullRomCurve3(offsetData); curveLine.geometry.vertices = curveData.getPoints(10); curveLine.geometry.verticesNeedUpdate = true; } requestAnimationFrame(lineAnimate); } lineAnimate();
最后就是布置场景和事件了
// 初始化 function init() { container = document.getElementById('zh_globe_container'); scene = new THREE.Scene(); var bgTexture = new THREE.TextureLoader().load("images/textures/starfield.jpg"); scene.background = bgTexture; camera = new THREE.PerspectiveCamera(50, winWth/winHgt, 1, 2000); camera.up.x = 0; camera.up.y = 1; camera.up.z = 0; camera.position.x = 0; camera.position.y = 0; camera.position.z = 400; camera.lookAt(0,0,0); group = new THREE.Group(); scene.add(group); // 地球 globe(); // 飞机 plane(); // 星点 stars(); // 半球光 lights(); // 渲染器 renderer = new THREE.WebGLRenderer({antialias: true, preserveDrawingBuffer: true}); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(winWth, winHgt); container.appendChild(renderer.domElement); // 盘旋控制 var orbitControl = new THREE.OrbitControls(camera, renderer.domElement); orbitControl.minDistrance = 20; orbitControl.maxDistrance = 50; orbitControl.maxPolarAngle = Math.PI/2; // 性能测试 stats = new Stats(); container.appendChild(stats.dom); // resize事件 window.addEventListener('resize', onWindowResize, false); } // 窗口大小改变 function onWindowResize() { camera.aspect = window.innerWidth/window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } // 渲染 function render() { group.rotation.y -= 0.0005; renderer.render(scene, camera); } // 动画 function animate() { requestAnimationFrame(animate); render(); stats.update(); } init(); animate();
完整代码: