摘要:官網(wǎng)首先我們來看下要實現(xiàn)的效果這個縮小后的圖片,下面我們來看下近距離的動態(tài)效果。。效果比較簡陋,需要后期再處理。。。下面進入主題,代碼篇。。
threejs官網(wǎng):https://threejs.org/
首先我們來看下要實現(xiàn)的效果
這個縮小后的圖片,下面我們來看下近距離的動態(tài)效果。。
效果比較簡陋,需要后期再處理。。。
下面進入主題,代碼篇。。
HTML部分:
全球航班
JS部分(globe.js)
1、實現(xiàn)地球
地球貼圖(可以在網(wǎng)上下載)
// 地球 function globe() { var globeTextureLoader = new THREE.TextureLoader(); globeTextureLoader.load("images/textures/earth.jpg", function (texture) { var globeGgeometry = new THREE.SphereGeometry(200, 100, 100); var globeMaterial = new THREE.MeshStandardMaterial({map: texture}); var globeMesh = new THREE.Mesh(globeGgeometry, globeMaterial); group.add(globeMesh); group.rotation.x = THREE.Math.degToRad(35); group.rotation.y = THREE.Math.degToRad(170); }); }
2、添加球面光源(這里使用的是半球光)
// 光 function lights() { var hemisphereLight = new THREE.HemisphereLight(0xffffff, 0x333333, 2); hemisphereLight.position.x = 0; hemisphereLight.position.y = 0; hemisphereLight.position.z = -200; group.add(hemisphereLight); }
3、添加星點
// 星點 function stars() { var starsGeometry = new THREE.Geometry(); for (var i = 0; i < 2000; i ++) { var starVector = new THREE.Vector3( THREE.Math.randFloatSpread(2000), THREE.Math.randFloatSpread(2000), THREE.Math.randFloatSpread(2000) ); starsGeometry.vertices.push(starVector); } var starsMaterial = new THREE.PointsMaterial({color: 0x888888}) var starsPoint = new THREE.Points(starsGeometry, starsMaterial); group.add(starsPoint); }
4、添加飛機
這里需要我們把 經(jīng)緯度坐標 轉成 xyz 坐標
// 獲取position function getPosition(lng, lat, alt) { var phi = (90-lat)*(Math.PI/180), theta = (lng+180)*(Math.PI/180), radius = alt+200, x = -(radius * Math.sin(phi) * Math.cos(theta)), z = (radius * Math.sin(phi) * Math.sin(theta)), y = (radius * Math.cos(phi)); return {x: x, y: y, z: z}; }
畫飛機
// 飛機形狀(不想畫的,可以下載個 飛機模型 使用加載器加載進來) var planeShape = new THREE.Shape(); planeShape.moveTo( 0, 0); planeShape.lineTo(0.2, -0.2); planeShape.lineTo(0.2, -1.3); planeShape.lineTo(1.6,-2.7); planeShape.lineTo(1.6,-3); planeShape.lineTo(0.2, -2.1); planeShape.lineTo(0.2, -3); planeShape.lineTo(0.5, -3.4); planeShape.lineTo(0.5, -3.7); planeShape.lineTo(0, -3.3); planeShape.lineTo(-0.5, -3.7); planeShape.lineTo(-0.5, -3.4); planeShape.lineTo(-0.2, -3); planeShape.lineTo(-0.2, -2.1); planeShape.lineTo(-1.6,-3); planeShape.lineTo(-1.6,-2.7); planeShape.lineTo(-0.2, -1.3); planeShape.lineTo(-0.2, -0.2); var planeGeometry = new THREE.ShapeGeometry(planeShape); // 飛機材質 var planeMaterial = new THREE.MeshPhongMaterial({color: 0x0FB4DD, side: THREE.DoubleSide, depthTest: true});
depthTest作用是能否透過球體看到飛機,如果是false則旋轉到球體另一面也能看到飛機
添加飛機
// 添加飛機 function addPlane(item) { if(item.anum && item.lng && item.lat) { var plane = new THREE.Mesh(planeGeometry, planeMaterial); // 旋轉 plane.rotation.z = THREE.Math.degToRad(item.ang); // 定位 var position = getPosition(item.lng, item.lat, 5); plane.position.set(position.x, position.y, position.z); // 顯示/隱藏 // plane.visible = false; // 保存 planeMarkers[item.anum] = plane; // 添加到場景 group.add(plane); // 繪制歷史軌跡 drawHistoryTrack(item.anum); } }
繪制軌跡(使用socket來獲取的飛行軌跡經(jīng)緯度坐標點)
// 時間段 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=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); } } } }); }
如果要繪制所有點,且頭尾是在球面上的曲線,則需要兩次循環(huán)
var tcaRemainLength = tcaLength-tcaHalfLength for(var j=0; j0; 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,,當然也可以用頂點來實現(xiàn),如下
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);
另外不想用光點動畫的話,也可以用線動畫,實現(xiàn)原理是不斷更新頂點坐標,如下
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();
完整代碼:
var log = console.log.bind(console); var globeObj = (function() { "use strict"; // 判斷瀏覽器是否支持webgl if(!Detector.webgl) Detector.addGetWebGLMessage(); var container, stats; var camera, scene, renderer; var group; var mouseX = 0, mouseY = 0; var winWth = window.innerWidth, winHgt = window.innerHeight; // 獲取position function getPosition(lng, lat, alt) { var phi = (90-lat)*(Math.PI/180), theta = (lng+180)*(Math.PI/180), radius = alt+200, x = -(radius * Math.sin(phi) * Math.cos(theta)), z = (radius * Math.sin(phi) * Math.sin(theta)), y = (radius * Math.cos(phi)); return {x: x, y: y, z: z}; } // 飛機 function plane() { var socket = io("https://loc.variflight.com/*****此處接口地址不能給了", {transports: ["websocket"]}); var clientBounds = [52.793056,72.427908,2.970897,135.181814]; // 連接 socket.on("connect", function() { socket.emit("sub", clientBounds, -1, "", function(){}); }); // 飛機標記 var planeMarkers = {}; // 飛機形狀 var planeShape = new THREE.Shape(); planeShape.moveTo( 0, 0); planeShape.lineTo(0.2, -0.2); planeShape.lineTo(0.2, -1.3); planeShape.lineTo(1.6,-2.7); planeShape.lineTo(1.6,-3); planeShape.lineTo(0.2, -2.1); planeShape.lineTo(0.2, -3); planeShape.lineTo(0.5, -3.4); planeShape.lineTo(0.5, -3.7); planeShape.lineTo(0, -3.3); planeShape.lineTo(-0.5, -3.7); planeShape.lineTo(-0.5, -3.4); planeShape.lineTo(-0.2, -3); planeShape.lineTo(-0.2, -2.1); planeShape.lineTo(-1.6,-3); planeShape.lineTo(-1.6,-2.7); planeShape.lineTo(-0.2, -1.3); planeShape.lineTo(-0.2, -0.2); var planeGeometry = new THREE.ShapeGeometry(planeShape); // 飛機材質 var planeMaterial = new THREE.MeshPhongMaterial({color: 0x0FB4DD, side: THREE.DoubleSide, depthTest: true}); // 添加飛機 function addPlane(item) { if(item.anum && item.lng && item.lat) { var plane = new THREE.Mesh(planeGeometry, planeMaterial); // 旋轉 plane.rotation.z = THREE.Math.degToRad(item.ang); // 定位 var position = getPosition(item.lng, item.lat, 5); plane.position.set(position.x, position.y, position.z); // 顯示/隱藏 // plane.visible = false; // 保存 planeMarkers[item.anum] = plane; // 添加到場景 group.add(plane); // 繪制歷史軌跡 drawHistoryTrack(item.anum); } } // 時間段 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=2) { var tcaHalfLength = Math.ceil(tcaLength/2), tcaRemainLength = tcaLength-tcaHalfLength, vertexArr = []; /* 所有點 for(var j=0; j 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 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 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(); /*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();*/ } // 監(jiān)聽數(shù)據(jù)(添加并更新) socket.on("~", function(res) { if($.isEmptyObject(planeMarkers)) { $.each(res, function(i, item) { addPlane(item); }); } else { $.each(res, function(i, item) { if(planeMarkers[item.anum]) { if(item.lng && item.lat) { var pos = getPosition(item.lng, item.lat, 5); planeMarkers[item.anum].position.set(pos.x, pos.y, pos.z); } } else { addPlane(item); } }); } }); } // 地球 function globe() { var globeTextureLoader = new THREE.TextureLoader(); globeTextureLoader.load("images/textures/earth.jpg", function (texture) { var globeGgeometry = new THREE.SphereGeometry(200, 100, 100); var globeMaterial = new THREE.MeshStandardMaterial({map: texture}); var globeMesh = new THREE.Mesh(globeGgeometry, globeMaterial); group.add(globeMesh); group.rotation.x = THREE.Math.degToRad(35); group.rotation.y = THREE.Math.degToRad(170); }); } // 星點 function stars() { var starsGeometry = new THREE.Geometry(); for (var i = 0; i < 2000; i ++) { var starVector = new THREE.Vector3( THREE.Math.randFloatSpread(2000), THREE.Math.randFloatSpread(2000), THREE.Math.randFloatSpread(2000) ); starsGeometry.vertices.push(starVector); } var starsMaterial = new THREE.PointsMaterial({color: 0x888888}) var starsPoint = new THREE.Points(starsGeometry, starsMaterial); group.add(starsPoint); } // 光 function lights() { var hemisphereLight = new THREE.HemisphereLight(0xffffff, 0x333333, 2); hemisphereLight.position.x = 0; hemisphereLight.position.y = 0; hemisphereLight.position.z = -200; group.add(hemisphereLight); } // 初始化 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(); })();
場景背景圖
謝謝關注,如有幫助請推薦一下!
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/81639.html
摘要:在文末,我會附上一個可加載的模型方便學習中文藝術字渲染用原生可以很容易地繪制文字,但是原生提供的文字效果美化功能十分有限。 showImg(https://segmentfault.com/img/bVWYnb?w=900&h=385); WebGL 可以說是 HTML5 技術生態(tài)鏈中最為令人振奮的標準之一,它把 Web 帶入了 3D 的時代。 初識 WebGL 先通過幾個使用 Web...
摘要:首先是這個地球,得看看它是真還是假因為很多效果是拿雪碧圖做的,比如這里的旋轉的飛機,結果找到了并且在網(wǎng)站文件中搜到了,那就是沒跑了。 上個月底,在朋友圈看到一個號稱這可能是地球上最美的h5的分享,點進入后發(fā)現(xiàn)這個h5還很別致,思考了一會,決定要不高仿一個? 到今天為止,高仿基本完成, 線上地址 github地址 除了手機端的media控制沒有去兼容,其他的基本都給仿了。 那為了讓你...
摘要:比如地球自轉時播放背景音樂,動畫一旦開始則停止穿越云層后播放視頻,其他時候視頻是停止的。在上面做動畫分析的時候,是把這個開場動畫分開來設想的,但是上面的用上狀態(tài)機之后,意外的發(fā)現(xiàn)這個入場動畫可以以另外一個放進來。 上一篇知道如何制作threejs地球之后,就正式coding了,當然還是使用最心愛的Vue。本篇會有一些代碼,但是都是十幾行的獨立片段,相信你不用擔心。 布局 在進入本篇主題...
摘要:而是一款框架,由于其易用性被廣泛應用。如果要學習,拋棄那些復雜的原生接口從這款框架入手是一個不錯的選擇。需要相機,演員這里是地球,場景,導演。最后拍好了戲交給渲染器來制片,發(fā)布。狀態(tài)也在不停的更新。 WebGL入門demo three.js入門 開場白 哇哦,繪制氣球耶,在網(wǎng)頁上?對啊!厲害了!3D效果圖也能在網(wǎng)頁上繪制出來啊,這么好玩的事情,趕緊來看看! 這里是屬于WebGL的應用,...
閱讀 2311·2021-10-11 10:59
閱讀 2602·2021-10-11 10:58
閱讀 3304·2021-09-08 09:35
閱讀 3783·2021-09-02 15:21
閱讀 1455·2019-08-30 15:53
閱讀 2608·2019-08-29 14:16
閱讀 2068·2019-08-26 14:00
閱讀 2942·2019-08-26 13:52