JS實現環繞地球飛行的3D飛行線動畫效果(JS+HTML)
1.項目介紹
JS+HTML實現繞地球飛行的3D飛行線動畫效果,且3D地球可以隨意拖動和滑動縮放,畫面中心是藍色地球,地球表面上的兩點連線之間有光電隨機出現沿着拋物線軌跡3D飛行,可使用較好的瀏覽器打開,如microsoft edge打開,效果如下圖所示:
2.html源碼如下所示
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "//www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="//www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Threejs 實現環繞地球飛行的3D飛行線</title> <style> html, body { width: 100%; height: 100%; margin: 0; overflow: hidden; } </style> </head> <body> <div id="container"></div> <script src="js/three.103.min.js"></script> <script src="js/OrbitControls.js"></script> <script id="vertex-shader" type="x-shader/x-vertex"> varying vec3 vPosition; varying vec4 vColor; void main() { vPosition = position; vColor = vec4(color, 1.0); gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } </script> <script id="fragment-shader" type="x-shader/x-fragment"> uniform vec3 targetPos; // 目標位置 uniform float vLength; // 距離 uniform float time; varying vec3 vPosition; varying vec4 vColor; void main() { float dist = distance(vPosition, targetPos); vec4 color = vec4(vColor); float p = dist/vLength * 6.0 + time * 1.0; if (p < 3.1415926/2.0){ p = 0.0; } if (p > 3.1415926*2.0){ p = 0.0; } float a = sin(p); color.a = a; gl_FragColor = color; } </script> <script> var container = document.getElementById('container'); var scene, camera, renderer; var globeMesh = undefined; var groupDots, groupLines, groupAnimDots; var animateDots = []; // 小球運動點軌跡 var controls; // 配置參數 var params = { pointsLength: 20, // 點數 globeRadius: 100 // 地球半徑 } var vertexShader = document.getElementById('vertex-shader').innerHTML; var fragmentShader = document.getElementById('fragment-shader').innerHTML; const PI2 = Math.PI * 2; // 弧度的取值為0-2π var timer = -PI2; // 預製件 var Prefab = { Sphere: (function() { var instance; return function(clone = true) { if (!instance) { instance = new createSphere(); } if (clone) return instance.clone(); else return instance; } })() } init(); update(); function init() { // 場景 scene = new THREE.Scene(); groupDots = new THREE.Group(); groupLines = new THREE.Group(); groupAnimDots = new THREE.Group(); scene.add(groupDots, groupLines, groupAnimDots); // 相機 camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000); camera.position.x = -200; camera.position.y = 200; camera.position.z = -200; camera.lookAt(scene.position); // 渲染器 renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(window.devicePixelRatio); container.appendChild(renderer.domElement); // 光 var light = new THREE.HemisphereLight(0xffffff, 0xffffff, 1); scene.add(light); // 控制器 controls = new THREE.OrbitControls(camera, renderer.domElement); controls.minDistance = 200; controls.maxDistance = 400; controls.rotateSpeed = 0.5; controls.enableDamping = true; controls.enablePan = false; initGlobe(); initLines(); window.addEventListener('resize', onWindowResize, false); } function update() { requestAnimationFrame(update); renderer.render(scene, camera); timer += 0.02; if (timer > Math.PI * 1.5) { timer = -Math.PI * 1.5; } groupLines.children.forEach(function(item) { item.material.uniforms.time.value = timer; }); // console.log(globeMesh.material.map.offset.x) controls.update(); } function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } function initGlobe() { // 地球 var geo = new THREE.SphereGeometry(params.globeRadius, 32, 32); var texture = new THREE.TextureLoader().load('img/earth.jpg'); texture.minFilter = THREE.LinearFilter; var material = new THREE.MeshPhongMaterial({ map: texture, // wireframe: true }); globeMesh = new THREE.Mesh(geo, material); scene.add(globeMesh); } // 地球飛線和點 function initLines() { // 球面隨機點 for (let i = 0; i < params.pointsLength; i++) { addPoints(groupDots, params.globeRadius); } // 曲線 groupDots.children.forEach(function(elem, index) { // 從第一個點到其它點 if (elem != groupDots.children[0]) { var line = addLines(groupDots.children[index - 1].position, elem.position); animateDots.push(line.curve.getPoints(100)); } }); } // 3d球面取點 function getEarthPos(radius, a, b) { var x = radius * Math.sin(a) * Math.cos(b); var y = radius * Math.sin(a) * Math.sin(b); var z = radius * Math.cos(a); return { x, y, z }; } // 添加隨機點 function addPoints(group, radius) { var mesh = new Prefab.Sphere(); var pos = getEarthPos(radius, PI2 * Math.random(), PI2 * Math.random()); mesh.position.set(pos.x, pos.y, pos.z); group.add(mesh); } function addLines(v0, v3) { var angle = v0.angleTo(v3); var vtop = v0.clone().add(v3); vtop = vtop.normalize().multiplyScalar(params.globeRadius); var n; if (angle <= 1) { n = params.globeRadius / 5 * angle; } else if (angle > 1 && angle < 2) { n = params.globeRadius / 5 * Math.pow(angle, 2); } else { n = params.globeRadius / 5 * Math.pow(angle, 1.5); } var v1 = v0.clone().add(vtop).normalize().multiplyScalar(params.globeRadius + n); var v2 = v3.clone().add(vtop).normalize().multiplyScalar(params.globeRadius + n); // addLineHelper(globeMesh.position, v1); // addLineHelper(globeMesh.position, v2); // addLineHelper(globeMesh.position, vtop) // 三維三次貝塞爾曲線(v0起點,v1第一個控制點,v2第二個控制點,v3終點) var curve = new THREE.CubicBezierCurve3(v0, v1, v2, v3); var points = curve.getPoints(50); var vertices = [], colors = []; points.forEach(function(item, index) { vertices.push(item.x, item.y, item.z); colors.push(index / points.length, index / points.length, index / points.length); }); var geometry = new THREE.BufferGeometry(); geometry.attributes.position = new THREE.Float32BufferAttribute(vertices, 3) var material = createLineMaterial(v0, v3); var lineMesh = new THREE.Line(geometry, material); groupLines.add(lineMesh); return { curve: curve, lineMesh: lineMesh }; } function createLineMaterial(myPos, targetPos) { var uniforms = { targetPos: { value: targetPos }, vLength: { value: myPos.distanceTo(targetPos) }, time: { value: timer } }; var material = new THREE.ShaderMaterial({ uniforms: uniforms, vertexShader: vertexShader, fragmentShader: fragmentShader, transparent: true, vertexColors: THREE.VertexColors }); return material; } function createSphere() { var geometry = new THREE.SphereBufferGeometry(1); var material = new THREE.MeshBasicMaterial({ color: 0x00ffff }); var mesh = new THREE.Mesh(geometry, material); return mesh; } function addPointHelper(pos) { var mesh = new Prefab.Sphere(); mesh.material = new THREE.MeshBasicMaterial({ color: 0xff0000 }); mesh.position.copy(pos); scene.add(mesh); } function addLineHelper(pos1, pos2) { var material = new THREE.LineBasicMaterial({ color: 0x0000ff }); var geometry = new THREE.Geometry(); geometry.vertices.push(pos1, pos2); var line = new THREE.Line(geometry, material); scene.add(line); } </script> </body> </html>
3.JS部分代碼由於代碼量較大這裡就不黏貼了
4.文件目錄如下
5.瀏覽器要支持HTML5與CSS3才有效果。
整個項目源碼下載地址://download.csdn.net/download/xipengbozai/16595841