欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Threejs實(shí)現(xiàn)滴滴官網(wǎng)首頁地球動畫功能

 更新時間:2020年07月13日 10:23:10   作者:龐永勝  
這篇文章主要介紹了Threejs實(shí)現(xiàn)滴滴官網(wǎng)首頁地球動畫效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

偶然翻滴滴官網(wǎng)看到首頁下翻第六欄(大概)有個絢麗的地球的三維動畫,試著用there.js實(shí)現(xiàn)了下,基本實(shí)現(xiàn)了動畫效果,不過還是有些問題;這個動畫看似簡單,但也用到好的繪制方法和計(jì)算,這里先寫一下主要功能的實(shí)現(xiàn);

先看示例:http://39.106.166.212:8080/webgl/t4(由于是寫dome的一個項(xiàng)目,內(nèi)容較多沒做優(yōu)化,第一次加載會會比較慢,需多等待幾秒)

(lice這個截圖工具也是很不好用,每次都截到一半 ╮(╯﹏╰)╭)

一、 3d繪制場景的構(gòu)建

繪制一個3d程序首先需要添加 渲染器,場景,照相機(jī) 這些元素,這里補(bǔ)充一個燈光;

1、渲染器

首先創(chuàng)建一個渲染器,參數(shù)為頁面中的canvas元素,

渲染器的作用就是把3d場景的內(nèi)容結(jié)合照相機(jī)渲染到頁面中,

最后將畫布背景設(shè)為白色。

const renderer = new Three.WebGLRenderer({canvas: this.$refs.thr});
renderer.setClearColor(0x000000);

2、場景

場景顧名思義,就是添加一個你發(fā)揮(繪制)的場地,后面所有繪制的元素都要添加到場景中;

cosnt scene = new Three.Scene();

3、照相機(jī)

照相機(jī)就像人的視覺或說從什么角度去看場景,看場景的位置和視線的方向決定了渲染到頁面的內(nèi)容。故一般需要設(shè)置兩個參數(shù)相機(jī)位置position、視線方向lookAt,,在webgl其實(shí)是需要三組參數(shù)視點(diǎn),觀察點(diǎn),和上方向。thresjs中好像是默認(rèn)Y軸為上方向了,這里使用透視相機(jī)。

const camera = new THREE.PerspectiveCamera(45, 500 / 500, 1, 1500);
camera.position.set(100, 100, 1000);
camera.lookAt(new THREE.Vector3(0, 0, 0));
scene.add(this.camera);

 4、燈光

這里使用THREE.HemisphereLight光,可以更加貼近自然的戶外光照效;

let light = new THREE.HemisphereLight(0xffffff); 
light.position.set(0, 0, 200); 
scene.add(light)

以上我們基本的繪制要素已添加完成,下面開始繪制各個幾何體內(nèi)容;

幾何體的繪制有三部:創(chuàng)建幾何體,創(chuàng)建材料,添加網(wǎng)格模型;

二、地球的繪制

threejs中提供了球體的繪制,我們只需創(chuàng)建一個球體,材料使用紋理貼圖方式添加地圖;

貼圖圖片資源是我從官網(wǎng)上找的

const geometry = new THREE.SphereGeometry(this.radius, 100, 100); // 球體  
const textureLoader = new THREE.TextureLoader(); // 創(chuàng)建紋理貼圖  
const texture = textureLoader.load(require("@/assets/map.jpg"),texture => { 
 let material = new THREE.MeshLambertMaterial({map: texture,transparent: true,});
 let mesh = new THREE.Mesh(geometry, material); 
 scene.add(mesh);
});

由于圖片加載是異步的 ,這里需等圖片加載完成后才能創(chuàng)建材質(zhì);

這里我們就創(chuàng)建好了一個地球模型,接著還要讓其轉(zhuǎn)動起來;(中間為xyz坐標(biāo)軸)

threejs提供了幾何體的基本3d變換,直接使用rotateY(angleChange)根據(jù)時間設(shè)置其繞y軸(綠色軸)旋轉(zhuǎn)角度即可;

三、球面坐標(biāo)點(diǎn)的繪制

1、在繪制球面位置點(diǎn)時,需先前先看下球坐標(biāo)系,確定點(diǎn)的位置,webgl中坐標(biāo)方向與下圖不一致,但是對點(diǎn)的表示方法是一致的;

球面上任意點(diǎn)可以用r,θ,φ表示,也可通過以下公式轉(zhuǎn)化到直角坐標(biāo)系中

x=rsinθcosφ.
y=rsinθsinφ.
z=rcosθ

但實(shí)際中地球位置我們一般也會使用經(jīng)緯度表示。。。 下面寫個經(jīng)緯度轉(zhuǎn)坐標(biāo)的方法。

threejs提供了THREE.Math.degToRad方法可以將經(jīng)緯度轉(zhuǎn)化為θ,φ,轉(zhuǎn)化方法如下,這里為了方便后面使用,我直接返回一個3維向量;

getPosition(longitude, latitude, radius = this.radius) {  // 經(jīng)度,緯度轉(zhuǎn)換為坐標(biāo)  
 let lg = THREE.Math.degToRad(longitude);  
 let lt = THREE.Math.degToRad(latitude);  // 獲取x,y,z坐標(biāo)  
 let temp = radius * Math.cos(lt);  
 let x = temp * Math.sin(lg);  
 let y = radius * Math.sin(lt);  
 let z = temp * Math.cos(lg);  
 return new THREE.Vector3(x, y, z); 
}

2、知道了位置的表示方法后開始繪制表示位置的點(diǎn)
根據(jù)示例位置點(diǎn)的由點(diǎn)和一個圓環(huán)組成,我們先繪制一個二維平面內(nèi)的點(diǎn)和圓弧,在通過設(shè)置其位置和旋轉(zhuǎn)方式移動到目標(biāo)坐標(biāo)位置點(diǎn);

(這里也可以繪制幾何小球體來模擬)

(1)點(diǎn)的繪制

THREE.Shape是用來繪制二維平面內(nèi)的形狀的,設(shè)置其形狀為圓弧,即可實(shí)現(xiàn)一個原點(diǎn);

let shapePoint = new THREE.Shape();
shapePoint.absarc(0, 0, r - 4, 0, 2 * Math.PI, false);
let arcGeometry = new THREE.ShapeGeometry(shapePoint);
let arcMaterial = new THREE.MeshBasicMaterial({ color: 0x008080 });
let point = new THREE.Mesh(arcGeometry, arcMaterial);

(2)圓弧的繪制

let geometryLine = new THREE.Geometry();
let arc = new THREE.ArcCurve(0, 0, r, 0, 2 * Math.PI);
let points = arc.getPoints(40);
geometryLine.setFromPoints(points);
let LineMateri = new THREE.LineBasicMaterial({ color: 0x20b2aa });
let line = new THREE.Line(geometryLine, LineMateri);

(3)位置的設(shè)置

position.set(pos.x, pos.y, pos.z);

(4)二維圖形旋轉(zhuǎn)至球面
THREE.Spherical()方法 ,可將坐標(biāo)點(diǎn)轉(zhuǎn)化為坐標(biāo)點(diǎn)轉(zhuǎn)化回球坐標(biāo)系的偏移角度;

let spherical = new THREE.Spherical();
spherical.setFromCartesianCoords(pos.x, pos.y, pos.z);

設(shè)置位置點(diǎn)旋轉(zhuǎn)

Point.rotateX(spherical.phi - Math.PI / 2);
Point.rotateY(spherical.theta);

這里為什么要 - Math.PI / 2 是因?yàn)殚_始我們繪制時,平面是垂直于y軸的平面,參考下面這幅圖;

四、接著繪制鏈接球面兩點(diǎn)間的連線

連接兩點(diǎn)的曲線需在球面上方,

兩點(diǎn)間可以坐出無數(shù)條曲線,那么如何確定曲線,我們需自己再選擇合適的參數(shù)來確定;

首先想的是二階貝塞爾曲線,取兩點(diǎn)的中點(diǎn)為控制點(diǎn),但如果鏈接兩點(diǎn)剛好位于球面的兩個對稱端點(diǎn)(兩點(diǎn)間連線為直徑)時,控制點(diǎn)需在無窮遠(yuǎn)處;

故考慮使用三階貝塞爾曲線,連接球面兩點(diǎn)和球心,三點(diǎn)確定的一個平面如下圖,

鏈接v1 v1,取中點(diǎn)c,鏈接oc,做一條射線,在射線取一點(diǎn)p,鏈接v1p,v2p,在v1,v2上取兩點(diǎn)作為控制點(diǎn);

求兩點(diǎn)的中點(diǎn)

getVCenter(v1, v2) { 
 let v = v1.add(v2); 
 return v.divideScalar(2); 
}

獲取兩點(diǎn)間指定比例位置坐標(biāo)

getLenVcetor(v1, v2, len) { 
 let v1v2Len = v1.distanceTo(v2); 
 return v1.lerp(v2, len / v1v2Len);
}

獲取貝塞爾控制點(diǎn)

getBezierPoint(v0, v3) {   
 let angle = (v0.angleTo(v3) * 180) / Math.PI; // 0 ~ Math.PI  // 計(jì)算向量夾角 
 let aLen = angle * 2.5,  
  hLen = angle * angle * 50;  
 let p0 = new THREE.Vector3(0, 0, 0);  // 法線向量  
 let rayLine = new THREE.Ray(p0, this.getVCenter(v0.clone(), v3.clone()));  // 頂點(diǎn)坐標(biāo) 
 let vtop = rayLine.at(hLen / rayLine.at(1).distanceTo(p0), vtop); // 位置  
 // 控制點(diǎn)坐標(biāo)  
 let v1 = this.getLenVcetor(v0.clone(), vtop, aLen);  
 let v2 = this.getLenVcetor(v3.clone(), vtop, aLen);  
 return {  
 v1: v1,  
 v2: v2  
 }; 
},

繪制三次貝塞爾曲線

drawLine(longitude, latitude, longitude2, latitude2) {  
 let geometry = new THREE.Geometry(); //聲明一個幾何體對象Geometry
 let v0 = this.getPosition(longitude, latitude, this.radius);  
 let v3 = this.getPosition(longitude2, latitude2, this.radius);
 let { v1, v2 } = this.getBezierPoint(v0, v3); // 三維二次貝賽爾曲線  
 let curve = new THREE.CubicBezierCurve3(v0, v1, v2, v3);
 let curvePoints = curve.getPoints(100);
 geometry.setFromPoints(curvePoints);
 let material = new THREE.LineBasicMaterial({  
 color: 0xff7e41  
 });
 let line = new THREE.Line(geometry, material);
 this.group.add(line);
 this.sport(curvePoints); 
},

五、小球的運(yùn)動軌跡

小球的動畫我們使用three的幀動畫,路徑可以直接使用上一步中的曲線;

1、繪制小球

drawSportPoint(position, name) { 
 let box = new THREE.SphereGeometry(6, 6, 6); 
 let material = new THREE.MeshLambertMaterial({  
 color: 0x00bfff 
 });  //材質(zhì)對象 
 let mesh = new THREE.Mesh(box, material);
 mesh.name = name; 
 mesh.position.set(position.x, position.y, position.z); 
 this.groupBall.add(mesh); 
 this.group.add(this.groupBall); 
 return mesh;
}

2、讓小球動起來

sport(curvePoints, index) {  
 const Ball = this.drawSportPoint(curvePoints[0]);  
 let arr = Array.from(Array(101), (v, k) => k);  // 生成一個時間序列  
 let times = new Float32Array(arr);
 let posArr = [];  
 curvePoints.forEach(elem => {  
 posArr.push(elem.x, elem.y, elem.z);  
 });  // 創(chuàng)建一個和時間序列相對應(yīng)的位置坐標(biāo)系列  
 let values = new Float32Array(posArr); // 創(chuàng)建一個幀動畫的關(guān)鍵幀數(shù)據(jù),曲線上的位置序列對應(yīng)一個時間序列  
 let posTrack = new THREE.KeyframeTrack("Ball.position", times, values);  
 let duration = 101;  
 let clip = new THREE.AnimationClip("default", duration, [posTrack]);  
 this.mixer = new THREE.AnimationMixer(Ball);  
 let AnimationAction = this.mixer.clipAction(clip);  
 AnimationAction.timeScale = 20;  
 AnimationAction.play();
}

3、在requestAnimationFrame中添加觸發(fā)動畫

this.mixer.update(this.clock.getDelta());

到此這篇關(guān)于Threejs實(shí)現(xiàn)滴滴官網(wǎng)首頁地球動畫的文章就介紹到這了,更多相關(guān)Threejs滴滴官網(wǎng)首頁地球動畫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • javaScript使用EL表達(dá)式的幾種方式

    javaScript使用EL表達(dá)式的幾種方式

    這篇文章主要介紹了javaScript如何使用EL表達(dá)式,有哪幾種不錯的方式,需要的朋友可以參考下
    2014-05-05
  • 在Postman的腳本中如何使用pm對象獲取接口的請求參數(shù)

    在Postman的腳本中如何使用pm對象獲取接口的請求參數(shù)

    這篇文章主要介紹了在Postman的腳本中如何使用pm對象獲取接口的請求參數(shù),本文通過實(shí)例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • 詳解webpack4.x之搭建前端開發(fā)環(huán)境

    詳解webpack4.x之搭建前端開發(fā)環(huán)境

    這篇文章主要介紹了詳解webpack4.x之搭建前端開發(fā)環(huán)境,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-03-03
  • 老生常談Javascript中的原型和this指針

    老生常談Javascript中的原型和this指針

    下面小編就為大家?guī)硪黄仙U凧avascript中的原型和this指針。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,祝大家游戲愉快哦
    2016-10-10
  • JavaScript基礎(chǔ)入門之錯誤捕獲機(jī)制

    JavaScript基礎(chǔ)入門之錯誤捕獲機(jī)制

    初級開發(fā)人員往往很少使用js的拋出和捕獲異常,但拋出和捕獲異常往往是非常必要的,這篇文章主要給大家介紹了關(guān)于JavaScript基礎(chǔ)入門之錯誤捕獲機(jī)制的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • Track Image Loading效果代碼分析

    Track Image Loading效果代碼分析

    Track Image Loading效果代碼分析...
    2007-08-08
  • JavaScript狀態(tài)模式及適配器模式使用講解

    JavaScript狀態(tài)模式及適配器模式使用講解

    這篇文章主要介紹了理解JavaScript中的狀態(tài)模式及適配器模式,適配器模式即Adapter Pattern,是作為兩個不兼容的接口之間的橋梁。這種類型的設(shè)計(jì)模式屬于結(jié)構(gòu)型模式,下文更多相關(guān)介紹需要的小伙伴可以參考一下
    2022-12-12
  • html5+CSS 實(shí)現(xiàn)禁止IOS長按復(fù)制粘貼功能

    html5+CSS 實(shí)現(xiàn)禁止IOS長按復(fù)制粘貼功能

    因?yàn)樵谝苿佣薃PP需要實(shí)現(xiàn)長按執(zhí)行別的事件,但是在iOS系統(tǒng)有默認(rèn)的長按選擇復(fù)制粘貼。禁止在網(wǎng)上找了很多資料,下面小編給大家分享解決方案,一起看看吧
    2016-12-12
  • JavaScript中l(wèi)ayer關(guān)閉指定彈出窗口方法總結(jié)

    JavaScript中l(wèi)ayer關(guān)閉指定彈出窗口方法總結(jié)

    這篇文章主要給大家介紹了關(guān)于JavaScript中l(wèi)ayer關(guān)閉指定彈出窗口方法的相關(guān)資料,layer是layui的一個彈出層組件,但是可以作為獨(dú)立組件使用,需要的朋友可以參考下
    2023-10-10
  • SWFObject基本用法實(shí)例分析

    SWFObject基本用法實(shí)例分析

    這篇文章主要介紹了SWFObject基本用法,實(shí)例分析了SWFObject操作Flash文件的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07

最新評論