国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

看完這篇,你也可以實(shí)現(xiàn)一個(gè)360度全景插件

Michael_Lin / 3403人閱讀

摘要:兩種相機(jī)的區(qū)別目前提供了幾種不同的相機(jī),最常用的,也是下面插件中使用的兩種相機(jī)是透視相機(jī)正交投影相機(jī)。上面的圖很清楚的解釋了兩種相機(jī)的區(qū)別右側(cè)是正交投影相機(jī)他不具有透視效果,即物體的大小不受遠(yuǎn)近距離的影響,對(duì)應(yīng)的是投影中的正交投影。

導(dǎo)讀

本文從繪圖基礎(chǔ)開始講起,詳細(xì)介紹了如何使用Three.js開發(fā)一個(gè)功能齊全的全景插件。

我們先來看一下插件的效果:

如果你對(duì)Three.js已經(jīng)很熟悉了,或者你想跳過基礎(chǔ)理論,那么你可以直接從全景預(yù)覽開始看起。

本項(xiàng)目的github地址:github.com/ConardLi/tp…

一、理清關(guān)系 1.1 OpenGL

OpenGL是用于渲染2D、3D量圖形的跨語(yǔ)言、跨平臺(tái)的應(yīng)用程序編程接口(API)

這個(gè)接口由近350個(gè)不同的函數(shù)調(diào)用組成,用來從簡(jiǎn)單的圖形比特繪制復(fù)雜的三維景象。

OpenGL ESOpenGL三維圖形API的子集,針對(duì)手機(jī)、PDA和游戲主機(jī)等嵌入式設(shè)備而設(shè)計(jì)。

基于OpenGL,一般使用CCpp開發(fā),對(duì)前端開發(fā)者來說不是很友好。

1.2 WebGL

WebGLJavaScriptOpenGL ES 2.0結(jié)合在一起,從而為前端開發(fā)者提供了使用JavaScript編寫3D效果的能力。

WebGLHTML5 Canvas提供硬件3D加速渲染,這樣Web開發(fā)人員就可以借助系統(tǒng)顯卡來在瀏覽器里更流暢地展示3D場(chǎng)景和模型了,還能創(chuàng)建復(fù)雜的導(dǎo)航和數(shù)據(jù)視覺化。

1.3 Canvas

Canvas是一個(gè)可以自由制定大小的矩形區(qū)域,可以通過JavaScript可以對(duì)矩形區(qū)域進(jìn)行操作,可以自由的繪制圖形,文字等。

一般使用Canvas都是使用它的2dcontext功能,進(jìn)行2d繪圖,這是其本身的能力。

和這個(gè)相對(duì)的,WebGL是三維,可以描畫3D圖形,WebGL,想要在瀏覽器上進(jìn)行呈現(xiàn),它必須需要一個(gè)載體,這個(gè)載體就是Canvas,區(qū)別于之前的2dcontext,還可以從Canvas中獲取webglcontext

1.4 Three.js

我們先來從字面意思理解下:Three代表3Djs代表JavaScript,即使用JavaScript來開發(fā)3D效果。

Three.js是使用JavaScript對(duì) WebGL接口進(jìn)行封裝與簡(jiǎn)化而形成的一個(gè)易用的3D庫(kù)。

直接使用WebGL進(jìn)行開發(fā)對(duì)于開發(fā)者來說成本相對(duì)來說是比較高的,它需要你掌握較多的計(jì)算機(jī)圖形學(xué)知識(shí)。

Three.js在一定程度上簡(jiǎn)化了一些規(guī)范和難以理解的概念,對(duì)很多API進(jìn)行了簡(jiǎn)化,這大大降低了學(xué)習(xí)和開發(fā)三維效果成本。

下面我們來具體看一下使用Three.js必須要知道的知識(shí)。

二、Three.js基礎(chǔ)知識(shí)

使用Three.js繪制一個(gè)三維效果,至少需要以下幾個(gè)步驟:

創(chuàng)建一個(gè)容納三維空間的場(chǎng)景 — Sence

將需要繪制的元素加入到場(chǎng)景中,對(duì)元素的形狀、材料、陰影等進(jìn)行設(shè)置

給定一個(gè)觀察場(chǎng)景的位置,以及觀察角度,我們用相機(jī)對(duì)象(Camera)來控制

將繪制好的元素使用渲染器(Renderer)進(jìn)行渲染,最終呈現(xiàn)在瀏覽器上

拿電影來類比的話,場(chǎng)景對(duì)應(yīng)于整個(gè)布景空間,相機(jī)是拍攝鏡頭,渲染器用來把拍攝好的場(chǎng)景轉(zhuǎn)換成膠卷。

2.1 場(chǎng)景

場(chǎng)景允許你設(shè)置哪些對(duì)象被three.js渲染以及渲染在哪里。

我們?cè)趫?chǎng)景中放置對(duì)象、燈光和相機(jī)。

很簡(jiǎn)單,直接創(chuàng)建一個(gè)Scene的實(shí)例即可。

 _scene = new Scene();
2.2 元素

有了場(chǎng)景,我們接下來就需要場(chǎng)景里應(yīng)該展示哪些東西。

一個(gè)復(fù)雜的三維場(chǎng)景往往就是由非常多的元素搭建起來的,這些元素可能是一些自定義的幾何體(Geometry),或者外部導(dǎo)入的復(fù)雜模型。

Three.js 為我們提供了非常多的Geometry,例如SphereGeometry(球體)、 TetrahedronGeometry(四面體)、TorusGeometry(圓環(huán)體)等等。

Three.js中,材質(zhì)(Material)決定了幾何圖形具體是以什么形式展現(xiàn)的。它包括了一個(gè)幾何體如何形狀以外的其他屬性,例如色彩、紋理、透明度等等,MaterialGeometry是相輔相成的,必須結(jié)合使用。

下面的代碼我們創(chuàng)建了一個(gè)長(zhǎng)方體體,賦予它基礎(chǔ)網(wǎng)孔材料(MeshBasicMaterial

    var geometry = new THREE.BoxGeometry(200, 100, 100);
    var material = new THREE.MeshBasicMaterial({ color: 0x645d50 });
    var mesh = new THREE.Mesh(geometry, material);
            _scene.add(mesh);

能以這個(gè)角度看到幾何體實(shí)際上是相機(jī)的功勞,這個(gè)我們下面的章節(jié)再介紹,這讓我們看到一個(gè)幾何體的輪廓,但是感覺怪怪的,這并不像一個(gè)幾何體,實(shí)際上我們還需要為它添加光照和陰影,這會(huì)讓幾何體看起來更真實(shí)。

基礎(chǔ)網(wǎng)孔材料(MeshBasicMaterial)不受光照影響的,它不會(huì)產(chǎn)生陰影,下面我們?yōu)閹缀误w換一種受光照影響的材料:網(wǎng)格標(biāo)準(zhǔn)材質(zhì)(Standard Material),并為它添加一些光照:

    var geometry = new THREE.BoxGeometry(200, 100, 100);
    var material = new THREE.MeshStandardMaterial({ color: 0x645d50 });
    var mesh = new THREE.Mesh(geometry, material);
    _scene.add(mesh);
    // 創(chuàng)建平行光-照亮幾何體
    var directionalLight = new THREE.DirectionalLight(0xffffff, 1);
     directionalLight.position.set(-4, 8, 12);
    _scene.add(directionalLight);
    // 創(chuàng)建環(huán)境光
    var ambientLight = new THREE.AmbientLight(0xffffff);
    _scene.add(ambientLight);

有了光線的渲染,讓幾何體看起來更具有3D效果,Three.js中光源有很多種,我們上面使用了環(huán)境光(AmbientLight)和平行光(DirectionalLight)。

環(huán)境光會(huì)對(duì)場(chǎng)景中的所有物品進(jìn)行顏色渲染。

平行光你可以認(rèn)為像太陽(yáng)光一樣,從極遠(yuǎn)處射向場(chǎng)景中的光。它具有方向性,也可以啟動(dòng)物體對(duì)光的反射效果。

除了這兩種光,Three.js還提供了其他幾種光源,它們適用于不同情況下對(duì)不同材質(zhì)的渲染,可以根據(jù)實(shí)際情況選擇。

2.3 坐標(biāo)系

在說相機(jī)之前,我們還是先來了解一下坐標(biāo)系的概念:

在三維世界中,坐標(biāo)定義了一個(gè)元素所處于三維空間的位置,坐標(biāo)系的原點(diǎn)即坐標(biāo)的基準(zhǔn)點(diǎn)。

最常用的,我們使用距離原點(diǎn)的三個(gè)長(zhǎng)度(距離x軸、距離y軸、距離z軸)來定義一個(gè)位置,這就是直角坐標(biāo)系。

在判定坐標(biāo)系時(shí),我們通常使用大拇指、食指和中指,并互為90度。大拇指代表X軸,食指代表Y軸,中指代表Z軸。

這就產(chǎn)生了兩種坐標(biāo)系:左手坐標(biāo)系和右手坐標(biāo)系。

Three.js中使用的坐標(biāo)系即右手坐標(biāo)系。

我們可以在我們的場(chǎng)景中添加一個(gè)坐標(biāo)系,這樣我們可以清楚的看到元素處于什么位置:

 var axisHelper = new THREE.AxisHelper(600);
 _scene.add(axisHelper);

其中紅色代表X軸,綠色代表Y軸,藍(lán)色代表Z軸。

2.4 相機(jī)

上面看到的幾何體的效果,如果不創(chuàng)建一個(gè)相機(jī)(Camera),是什么也看不到的,因?yàn)槟J(rèn)的觀察點(diǎn)在坐標(biāo)軸原點(diǎn),它處于幾何體的內(nèi)部。

相機(jī)(Camera)指定了我們?cè)谑裁次恢糜^察這個(gè)三維場(chǎng)景,以及以什么樣的角度進(jìn)行觀察。

2.4.1 兩種相機(jī)的區(qū)別

目前Three.js提供了幾種不同的相機(jī),最常用的,也是下面插件中使用的兩種相機(jī)是:PerspectiveCamera(透視相機(jī))、 OrthographicCamera(正交投影相機(jī))。

上面的圖很清楚的解釋了兩種相機(jī)的區(qū)別:

右側(cè)是 OrthographicCamera(正交投影相機(jī))他不具有透視效果,即物體的大小不受遠(yuǎn)近距離的影響,對(duì)應(yīng)的是投影中的正交投影。我們數(shù)學(xué)課本上所畫的幾何體大多數(shù)都采用這種投影。

左側(cè)是PerspectiveCamera(透視相機(jī)),這符合我們正常人的視野,近大遠(yuǎn)小,對(duì)應(yīng)的是投影中的透視投影。

如果你想讓場(chǎng)景看起來更真實(shí),更具有立體感,那么采用透視相機(jī)最合適,如果場(chǎng)景中有一些元素你不想讓他隨著遠(yuǎn)近放大縮小,那么采用正交投影相機(jī)最合適。

2.4.2 構(gòu)造參數(shù)

我們?cè)俜謩e來看看兩個(gè)創(chuàng)建兩個(gè)相機(jī)需要什么參數(shù):

_camera = new OrthographicCamera(left, right, top, bottom, near, far);

OrthographicCamera接收六個(gè)參數(shù),left, right, top, bottom分別對(duì)應(yīng)上、下、左、右、遠(yuǎn)、近的一個(gè)距離,超過這些距離的元素將不會(huì)出現(xiàn)在視野范圍內(nèi),也不會(huì)被瀏覽器繪制。實(shí)際上,這六個(gè)距離就構(gòu)成了一個(gè)立方體,所以OrthographicCamera的可視范圍永遠(yuǎn)在這個(gè)立方體內(nèi)。

_camera = new PerspectiveCamera(fov, aspect, near, far);

PerspectiveCamera接收四個(gè)參數(shù),nearfar和上面的相同,分別對(duì)應(yīng)相機(jī)可觀測(cè)的最遠(yuǎn)和最近距離;fov代表水平范圍可觀測(cè)的角度,fov越大,水平范圍能觀測(cè)到的范圍越廣;aspect代表水平方向和豎直方向可觀測(cè)距離的比值,所以fovaspect就可以確定垂直范圍內(nèi)能觀測(cè)到的范圍。

2.4.3 position、lookAt

關(guān)于相機(jī)還有兩個(gè)必須要知道的點(diǎn),一個(gè)是position屬性,一個(gè)是lookAt函數(shù):

position屬性指定了相機(jī)所處的位置。

lookAt函數(shù)指定相機(jī)觀察的方向。

實(shí)際上position的值和lookAt接收的參數(shù)都是一個(gè)類型為Vector3的對(duì)象,這個(gè)對(duì)象用來表示三維空間中的坐標(biāo),它有三個(gè)屬性:x、y、z分別代表距離x軸、距離y軸、距離z軸的距離。

下面,我們讓相機(jī)觀察的方向指向原點(diǎn),另外分別讓x、y、z為0,另外兩個(gè)參數(shù)不為0,看一下視野會(huì)發(fā)生什么變化:

_camera = new OrthographicCamera(-window.innerWidth / 2, window.innerWidth / 2, window.innerHeight / 2, -window.innerHeight / 2, 0.1, 1000);
 _camera.lookAt(new THREE.Vector3(0, 0, 0))

 _camera.position.set(0, 300, 600); // 1 - x為0

 _camera.position.set(500, 0, 600); // 2 - y為0

 _camera.position.set(500, 300, 0); // 3 - z為0

很清楚的看到position決定了我們視野的出發(fā)點(diǎn),但是鏡頭指向的方向是不變的。

下面我們將position固定,改變相機(jī)觀察的方向:

_camera = new OrthographicCamera(-window.innerWidth / 2, window.innerWidth / 2, window.innerHeight / 2, -window.innerHeight / 2, 0.1, 1000);
_camera.position.set(500, 300, 600); 

_camera.lookAt(new THREE.Vector3(0, 0, 0)) // 1 - 視野指向原點(diǎn)

_camera.lookAt(new THREE.Vector3(200, 0, 0)) // 2 - 視野偏向x軸

可見:我們視野的出發(fā)點(diǎn)是相同的,但是視野看向的方向發(fā)生了改變。

2.4.4 兩種相機(jī)對(duì)比

好,有了上面的基礎(chǔ),我們?cè)賮韺憙蓚€(gè)例子看一看兩個(gè)相機(jī)的視角對(duì)比,為了方便觀看,我們創(chuàng)建兩個(gè)位置不同的幾何體:

var geometry = new THREE.BoxGeometry(200, 100, 100);
var material = new THREE.MeshStandardMaterial({ color: 0x645d50 });
var mesh = new THREE.Mesh(geometry, material);
_scene.add(mesh);

var geometry = new THREE.SphereGeometry(50, 100, 100);
var ball = new THREE.Mesh(geometry, material);
ball.position.set(200, 0, -200);
_scene.add(ball);

正交投影相機(jī)視野:

_camera = new OrthographicCamera(-window.innerWidth / 2, window.innerWidth / 2, window.innerHeight / 2, -window.innerHeight / 2, 0.1, 1000);
_camera.position.set(0, 300, 600);
_camera.lookAt(new THREE.Vector3(0, 0, 0))

透視相機(jī)視野:

_camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1100);
_camera.position.set(0, 300, 600);
_camera.lookAt(new THREE.Vector3(0, 0, 0))

可見,這印證了我們上面關(guān)于兩種相機(jī)的理論

2.5 渲染器

上面我們創(chuàng)建了場(chǎng)景、元素和相機(jī),下面我們要告訴瀏覽器將這些東西渲染到瀏覽器上。

Three.js也為我們提供了幾種不同的渲染器,這里我們主要看WebGL渲染器(WebGLRenderer)。顧名思義:WebGL渲染器使用WebGL來繪制場(chǎng)景,其夠利用GPU硬件加速?gòu)亩岣咪秩拘阅堋?/p>

_renderer = new THREE.WebGLRenderer();

你需要將你使用Three.js繪制的元素添加到瀏覽器上,這個(gè)過程需要一個(gè)載體,上面我們介紹,這個(gè)載體就是Canvas,你可以通過_renderer.domElement獲取到這個(gè)Canvas,并將它給定到真實(shí)DOM中。

 _container = document.getElementById("conianer");
 _container.appendChild(_renderer.domElement);

使用setSize函數(shù)設(shè)定你要渲染的范圍,實(shí)際上它改變的就是上面Canvas的范圍:

_renderer.setSize(window.innerWidth, window.innerHeight);

現(xiàn)在,你已經(jīng)指定了一個(gè)渲染的載體和載體的范圍,你可以通過render函數(shù)渲染上面指定的場(chǎng)景和相機(jī):

_renderer.render(_scene, _camera);

實(shí)際上,你如果依次執(zhí)行上面的代碼,可能屏幕上還是黑漆漆的一片,并沒有任何元素渲染出來。

這是因?yàn)樯厦婺阋秩镜脑乜赡懿⑽幢患虞d完,你就執(zhí)行了渲染,并且只執(zhí)行了一次,這時(shí)我們需要一種方法,讓場(chǎng)景和相機(jī)進(jìn)行實(shí)時(shí)渲染,我們需要用到下面的方法:

2.6 requestAnimationFrame

window.requestAnimationFrame()告訴瀏覽器——你希望執(zhí)行一個(gè)動(dòng)畫,并且要求瀏覽器在下次重繪之前調(diào)用指定的回調(diào)函數(shù)更新動(dòng)畫。

該方法需要傳入一個(gè)回調(diào)函數(shù)作為參數(shù),該回調(diào)函數(shù)會(huì)在瀏覽器下一次重繪之前執(zhí)行。

window.requestAnimationFrame(callback);

若你想在瀏覽器下次重繪之前繼續(xù)更新下一幀動(dòng)畫,那么回調(diào)函數(shù)自身必須再次調(diào)用window.requestAnimationFrame()

使用者韓函數(shù)就意味著,你可以在requestAnimationFrame不停的執(zhí)行繪制操作,瀏覽器就實(shí)時(shí)的知道它需要渲染的內(nèi)容。

當(dāng)然,某些時(shí)候你已經(jīng)不需要實(shí)時(shí)繪制了,你也可以使用cancelAnimationFrame立即停止這個(gè)繪制:

window.cancelAnimationFrame(myReq);

來看一個(gè)簡(jiǎn)單的例子:

        var i = 0;
        var animateName;
        animate();
        function animate() {
            animateName = requestAnimationFrame(animate);
            console.log(i++);
            if (i > 100) {
                cancelAnimationFrame(animateName);
            }
        }

來看一下執(zhí)行效果:

我們使用requestAnimationFrameThree.js的渲染器結(jié)合使用,這樣就能實(shí)時(shí)繪制三維動(dòng)畫了:

        function animate() {
            requestAnimationFrame(animate);
            _renderer.render(_scene, _camera);
        }

借助上面的代碼,我們可以簡(jiǎn)單實(shí)現(xiàn)一些動(dòng)畫效果:

        var y = 100;
        var option = "down";
        function animateIn() {
            animateName = requestAnimationFrame(animateIn);
            mesh.rotateX(Math.PI / 40);
            if (option == "up") {
                ball.position.set(200, y += 8, 0);
            } else {
                ball.position.set(200, y -= 8, 0);
            }
            if (y < 1) { option = "up"; }
            if (y > 100) { option = "down" }
        }

2.7 總結(jié)

上面的知識(shí)是Three.js中最基礎(chǔ)的知識(shí),也是最重要的和最主干的。

這些知識(shí)能夠讓你在看到一個(gè)復(fù)雜的三維效果時(shí)有一定的思路,當(dāng)然,要實(shí)現(xiàn)還需要非常多的細(xì)節(jié)。這些細(xì)節(jié)你可以去官方文檔中查閱。

下面的章節(jié)即告訴你如何使用Three.js進(jìn)行實(shí)戰(zhàn) — 實(shí)現(xiàn)一個(gè)360度全景插件。

這個(gè)插件包括兩部分,第一部分是對(duì)全景圖進(jìn)行預(yù)覽。

第二部分是對(duì)全景圖的標(biāo)記進(jìn)行配置,并關(guān)聯(lián)預(yù)覽的坐標(biāo)。

我們首先來看看全景預(yù)覽部分:

三、全景預(yù)覽

3.1 基本邏輯

將一張全景圖包裹在球體的內(nèi)壁

設(shè)定一個(gè)觀察點(diǎn),在球的圓心

使用鼠標(biāo)可以拖動(dòng)球體,從而改變我們看到全景的視野

鼠標(biāo)滾輪可以縮放,和放大,改變觀察全景的遠(yuǎn)近

根據(jù)坐標(biāo)在全景圖上掛載一些標(biāo)記,如文字、圖標(biāo)等,并且可以增加事件,如點(diǎn)擊事件

3.2 初始化

我們先把必要的基礎(chǔ)設(shè)施搭建起來:

場(chǎng)景、相機(jī)(選擇遠(yuǎn)景相機(jī),這樣可以讓全景看起來更真實(shí))、渲染器:

_scene = new THREE.Scene();
initCamera();
initRenderer();
animate();

// 初始化相機(jī)
function initCamera() {
    _camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1100);
    _camera.position.set(0, 0, 2000);
    _camera.lookAt(new THREE.Vector3(0, 0, 0));
}

// 初始化渲染器
function initRenderer() {
    _renderer = new THREE.WebGLRenderer();
    _renderer.setSize(window.innerWidth, window.innerHeight);
    _container = document.getElementById("panoramaConianer");
    _container.appendChild(_renderer.domElement);
}

// 實(shí)時(shí)渲染
function animate() {
    requestAnimationFrame(animate);
    _renderer.render(_scene, _camera);
}

下面我們?cè)趫?chǎng)景內(nèi)添加一個(gè)球體,并把全景圖作為材料包裹在球體上面:

var mesh = new THREE.Mesh(new THREE.SphereGeometry(1000, 100, 100),
new THREE.MeshBasicMaterial(
        { map: ImageUtils.loadTexture("img/p3.png") }
    ));
_scene.add(mesh);

然后我們看到的場(chǎng)景應(yīng)該是這樣的:

這不是我們想要的效果,我們想要的是從球的內(nèi)部觀察全景,并且全景圖是附著外球的內(nèi)壁的,而不是鋪在外面:

我們只要需將Materialscale的一個(gè)屬性設(shè)置為負(fù)值,材料即可附著在幾何體的內(nèi)部:

 mesh.scale.x = -1;

然后我們將相機(jī)的中心點(diǎn)移動(dòng)到球的中心:

 _camera.position.set(0, 0, 0);

現(xiàn)在我們已經(jīng)在全景球的內(nèi)部啦:

3.3 事件處理

全景圖已經(jīng)可以瀏覽了,但是你只能看到你眼前的這一塊,并不能拖動(dòng)它看到其他部分,為了精確的控制拖動(dòng)的速度和縮放、放大等場(chǎng)景,我們手動(dòng)為它增加一些事件:

監(jiān)聽鼠標(biāo)的mousedown事件,在此時(shí)將開始拖動(dòng)標(biāo)記_isUserInteracting設(shè)置為true,并且記錄起始的屏幕坐標(biāo),以及起始的相機(jī)lookAt的坐標(biāo)。

_container.addEventListener("mousedown", (event)=>{
  event.preventDefault();
  _isUserInteracting = true;
  _onPointerDownPointerX = event.clientX;
  _onPointerDownPointerY = event.clientY;
  _onPointerDownLon = _lon;
  _onPointerDownLat = _lat;
});

監(jiān)聽鼠標(biāo)的mousemove事件,當(dāng)_isUserInteractingtrue時(shí),實(shí)時(shí)計(jì)算當(dāng)前相機(jī)lookAt的真實(shí)坐標(biāo)。

_container.addEventListener("mousemove", (event)=>{
  if (_isUserInteracting) {
    _lon = (_onPointerDownPointerX - event.clientX) * 0.1 + _onPointerDownLon;
    _lat = (event.clientY - _onPointerDownPointerY) * 0.1 + _onPointerDownLat;
  }
});

監(jiān)聽鼠標(biāo)的mouseup事件,將_isUserInteracting設(shè)置為false

_container.addEventListener("mouseup", (event)=>{
 _isUserInteracting = false;
});

當(dāng)然,上面我們只是改變了坐標(biāo),并沒有告訴相機(jī)它改變了,我們?cè)?b>animate函數(shù)中來做這件事:

function animate() {
  requestAnimationFrame(animate);
  calPosition();
  _renderer.render(_scene, _camera);
  _renderer.render(_sceneOrtho, _cameraOrtho);
}

function calPosition() {
  _lat = Math.max(-85, Math.min(85, _lat));
  var phi = tMath.degToRad(90 - _lat);
  var theta = tMath.degToRad(_lon);
  _camera.target.x = _pRadius * Math.sin(phi) * Math.cos(theta);
  _camera.target.y = _pRadius * Math.cos(phi);
  _camera.target.z = _pRadius * Math.sin(phi) * Math.sin(theta);
  _camera.lookAt(_camera.target);
}

監(jiān)聽mousewheel事件,對(duì)全景圖進(jìn)行放大和縮小,注意這里指定了最大縮放范圍maxFocalLength和最小縮放范圍minFocalLength

_container.addEventListener("mousewheel", (event)=>{
  var ev = ev || window.event;
  var down = true;
  var m = _camera.getFocalLength();
  down = ev.wheelDelta ");0 : ev.detail > 0;
  if (down) {
    if (m > minFocalLength) {
      m -= m * 0.05
      _camera.setFocalLength(m);
    }
  } else {
    if (m < maxFocalLength) {
      m += m * 0.05
      _camera.setFocalLength(m);
    }
  }
});

來看一下效果吧:

3.4 增加標(biāo)記

在瀏覽全景圖的時(shí)候,我們往往需要對(duì)某些特殊的位置進(jìn)行一些標(biāo)記,并且這些標(biāo)記可能附帶一些事件,比如你需要點(diǎn)擊一個(gè)標(biāo)記才能到達(dá)下一張全景圖。

下面我們來看看如何在全景中增加標(biāo)記,以及如何為這些標(biāo)記添加事件。

我們可能不需要讓這些標(biāo)記隨著視野的變化而放大和縮小,基于此,我們使用正交投影相機(jī)來展現(xiàn)標(biāo)記,只需給它一個(gè)固定的觀察高度:

  _cameraOrtho = new THREE.OrthographicCamera(-window.innerWidth / 2, window.innerWidth / 2, window.innerHeight / 2, -window.innerHeight / 2, 1, 10);
  _cameraOrtho.position.z = 10;
  _sceneOrtho = new Scene();

利用精靈材料(SpriteMaterial)來實(shí)現(xiàn)文字標(biāo)記,或者圖片標(biāo)記:

// 創(chuàng)建文字標(biāo)記
function createLableSprite(name) {
  const canvas = document.createElement("canvas");
  const context = canvas.getContext("2d");
  const metrics = context.measureText(name);
  const width = metrics.width * 1.5;
  context.font = "10px 宋體";
  context.fillStyle = "rgba(0,0,0,0.95)";
  context.fillRect(2, 2, width + 4, 20 + 4);
  context.fillText(name, 4, 20);
  const texture = new Texture(canvas);
  const spriteMaterial = new SpriteMaterial({ map: texture });
  const sprite = new Sprite(spriteMaterial);
  sprite.name = name;
  const lable = {
    name: name,
    canvas: canvas,
    context: context,
    texture: texture,
    sprite: sprite
  };
  _sceneOrtho.add(lable.sprite);
  return lable;
}
// 創(chuàng)建圖片標(biāo)記
function createSprite(position, url, name) {
  const textureLoader = new TextureLoader();
  const ballMaterial = new SpriteMaterial({
    map: textureLoader.load(url)
  });
  const sp = {
    pos: position,
    name: name,
    sprite: new Sprite(ballMaterial)
  };
  sp.sprite.scale.set(32, 32, 1.0);
  sp.sprite.name = name;
  _sceneOrtho.add(sp.sprite);
  return sp;
}

創(chuàng)建好這些標(biāo)記,我們把它渲染到場(chǎng)景中。

我們必須告訴場(chǎng)景這些標(biāo)記的位置,為了直觀的理解,我們需要給這些標(biāo)記賦予一種坐標(biāo),這種坐標(biāo)很類似于經(jīng)緯度,我們叫它lonlat,具體是如何給定的我們?cè)谙旅娴恼鹿?jié):全景標(biāo)記中會(huì)詳細(xì)介紹。

在這個(gè)過程中,一共經(jīng)歷了兩次坐標(biāo)轉(zhuǎn)換:

第一次轉(zhuǎn)換:將“經(jīng)緯度”轉(zhuǎn)換為三維空間坐標(biāo),即我們上面講的那種x、y、z形式的坐標(biāo)。

使用geoPosition2World函數(shù)進(jìn)行轉(zhuǎn)換,得到一個(gè)Vector3對(duì)象,我們可以將當(dāng)前相機(jī)_camera作為參數(shù)傳入這個(gè)對(duì)象的project方法,這會(huì)得到一個(gè)標(biāo)準(zhǔn)化后的坐標(biāo),基于這個(gè)坐標(biāo)可以幫我們判斷標(biāo)記是否在視野范圍內(nèi),如下面的代碼,若標(biāo)準(zhǔn)化坐標(biāo)在-11的范圍內(nèi),則它會(huì)出現(xiàn)在我們的視野中,我們將它進(jìn)行準(zhǔn)確渲染。

第二次轉(zhuǎn)換:將三維空間坐標(biāo)轉(zhuǎn)換為屏幕坐標(biāo)。

如果我們直接講上面的三維空間坐標(biāo)坐標(biāo)應(yīng)用到標(biāo)記中,我們會(huì)發(fā)現(xiàn)無(wú)論視野如何移動(dòng),標(biāo)記的位置是不會(huì)有任何變化的,因?yàn)檫@樣算出來的坐標(biāo)永遠(yuǎn)是一個(gè)常量。

所以我們需要借助上面的標(biāo)準(zhǔn)化坐標(biāo),將標(biāo)記的三維空間坐標(biāo)轉(zhuǎn)換為真實(shí)的屏幕坐標(biāo),這個(gè)過程是worldPostion2Screen函數(shù)來實(shí)現(xiàn)的。

關(guān)于geoPosition2WorldworldPostion2Screen兩個(gè)函數(shù)的實(shí)現(xiàn),大家有興趣可以去我的github源碼中查看,這里就不多做解釋了,因?yàn)檫@又要牽扯到一大堆專業(yè)知識(shí)啦。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/7225.html

相關(guān)文章

  • 看完這篇你也可以實(shí)現(xiàn)一個(gè)360全景插件

    摘要:導(dǎo)讀本文從繪圖基礎(chǔ)開始講起,詳細(xì)介紹了如何使用開發(fā)一個(gè)功能齊全的全景插件。兩種相機(jī)的區(qū)別目前提供了幾種不同的相機(jī),最常用的,也是下面插件中使用的兩種相機(jī)是透視相機(jī)正交投影相機(jī)。 導(dǎo)讀 本文從繪圖基礎(chǔ)開始講起,詳細(xì)介紹了如何使用Three.js開發(fā)一個(gè)功能齊全的全景插件。 我們先來看一下插件的效果: showImg(https://segmentfault.com/img/remote/...

    XiNGRZ 評(píng)論0 收藏0
  • 看完這篇你也可以實(shí)現(xiàn)一個(gè)360全景插件

    摘要:導(dǎo)讀本文從繪圖基礎(chǔ)開始講起,詳細(xì)介紹了如何使用開發(fā)一個(gè)功能齊全的全景插件。兩種相機(jī)的區(qū)別目前提供了幾種不同的相機(jī),最常用的,也是下面插件中使用的兩種相機(jī)是透視相機(jī)正交投影相機(jī)。 導(dǎo)讀 本文從繪圖基礎(chǔ)開始講起,詳細(xì)介紹了如何使用Three.js開發(fā)一個(gè)功能齊全的全景插件。 我們先來看一下插件的效果: showImg(https://segmentfault.com/img/remote/...

    fredshare 評(píng)論0 收藏0
  • RGB、HSL、Hex網(wǎng)頁(yè)色彩碼,看完這篇全懂了

    摘要:再來做個(gè)練習(xí),如果我們想要黃色,那就是把紅色光跟綠色光混合起來,所以我們就把紅色光跟綠色光像這樣開到最大,你就能夠看到黃色了。 網(wǎng)頁(yè)使用到的色彩標(biāo)示方法中,從古早時(shí)期大家都在用的16進(jìn)位碼(#000000)、RGB色值標(biāo)示、HSL色彩標(biāo)示,其中網(wǎng)頁(yè)設(shè)計(jì)師最常使用的16進(jìn)位色碼標(biāo)示法,而16進(jìn)位碼又是如何計(jì)算色彩的呢?有沒有辦法直接腦袋就把色彩算出來?HSL色彩該如何運(yùn)用與記憶?有沒有什...

    hightopo 評(píng)論0 收藏0
  • RGB、HSL、Hex網(wǎng)頁(yè)色彩碼,看完這篇全懂了

    摘要:再來做個(gè)練習(xí),如果我們想要黃色,那就是把紅色光跟綠色光混合起來,所以我們就把紅色光跟綠色光像這樣開到最大,你就能夠看到黃色了。 網(wǎng)頁(yè)使用到的色彩標(biāo)示方法中,從古早時(shí)期大家都在用的16進(jìn)位碼(#000000)、RGB色值標(biāo)示、HSL色彩標(biāo)示,其中網(wǎng)頁(yè)設(shè)計(jì)師最常使用的16進(jìn)位色碼標(biāo)示法,而16進(jìn)位碼又是如何計(jì)算色彩的呢?有沒有辦法直接腦袋就把色彩算出來?HSL色彩該如何運(yùn)用與記憶?有沒有什...

    miguel.jiang 評(píng)論0 收藏0
  • JS+CSS3 360全景插件 - Watch3D.js

    摘要:日常閑扯從上一篇文章到這篇中間快過了一年了,時(shí)間真滴過得快。不是在下中間沒想過寫新的文章,而是自己確實(shí)變懶了體重。。。。。如果有人碰到過類似的問題并且找到了解決辦法的話,強(qiáng)烈歡迎留言或者私信,畢竟本人還是想寫個(gè)完整的插件的。 日常閑扯 從上一篇文章到這篇中間快過了一年了,時(shí)間真滴過得快。不是在下中間沒想過寫新的文章,而是自己確實(shí)變懶了(體重+1 +1 +1 +1....) 。。OTL...

    lpjustdoit 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<