前端如何實現一個圖片覆蓋的球體

earth_atmos_2048.jpg

簡介

作展現類項目的時候,一般要實現一些圓形選擇的效果。這個藉助cssrotate 就能夠實現.可是!要實現一個3D的帶圖片的旋轉球體該怎麼作呢?讓咱們開始吧。css

完整代碼codesandbox
完整代碼gitee
預覽地址
備用預覽地址

工具

three.js
OrbitControlshtml

繪製

建立一個場景

將場景藉助three.js來進行顯示,咱們須要如下幾個對象:場景、相機和渲染器,這樣咱們就能透過攝像機渲染出場景。git

let camera, scene, renderer;
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera(
    10,
    window.innerWidth / window.innerHeight,
    0.1,
    200
);
camera.position.set(30, 5, 20);
//renderer
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

咱們花一點點時間來解釋一下這裏發生了什麼。咱們如今創建了場景、相機和渲染器。canvas

three.js裏有幾種不一樣的相機,在這裏,咱們使用的是PerspectiveCamera(透視攝像機)。api

第一個參數是視野角度(FOV)。視野角度就是不管在何時,你所能在顯示器上看到的場景的範圍,數值越大越遠。瀏覽器

第二個參數是長寬比(aspect ratio)。 也就是你用一個物體的寬除以它的高的值。好比說,當你在一個寬屏電視上播放老電影時,能夠看到圖像彷彿是被壓扁的。app

接下來的兩個參數是近截面(near)和遠截面(far)。 當物體某些部分比攝像機的遠截面遠或者比近截面近的時候,該這些部分將不會被渲染到場景中。或許如今你不用擔憂這個值的影響,但將來爲了得到更好的渲染性能,你將能夠在你的應用程序裏去設置它。dom

接下來是渲染器。這裏是施展魔法的地方。除了咱們在這裏用到的WebGLRenderer渲染器以外,Three.js同時提供了其餘幾種渲染器,當用戶所使用的瀏覽器過於老舊,或者因爲其餘緣由不支持WebGL時,可使用這幾種渲染器進行降級。函數

除了建立一個渲染器的實例以外,咱們還須要在咱們的應用程序裏設置一個渲染器的尺寸。好比說,咱們可使用所須要的渲染區域的寬高,來讓渲染器渲染出的場景填充滿咱們的應用程序。所以,咱們能夠將渲染器寬高設置爲瀏覽器窗口寬高。對於性能比較敏感的應用程序來講,你可使用setSize傳入一個較小的值,例如window.innerWidth/2window.innerHeight/2,這將使得應用程序在渲染時,以一半的長寬尺寸渲染場景。工具

若是你但願保持你的應用程序的尺寸,可是以較低的分辨率來渲染,你能夠在調用setSize時,將updateStyle(第三個參數)設爲false。例如,假設你的<canvas> 標籤如今已經具備了100%的寬和高,調用setSize(window.innerWidth/2, window.innerHeight/2, false)將使得你的應用程序以一半的分辨率來進行渲染。

最後一步很重要,咱們將renderer(渲染器)的dom元素(renderer.domElement)添加到咱們的HTML文檔中。這就是渲染器用來顯示場景給咱們看的<canvas>元素。

「嗯,看起來很不錯,那你說的那個球體在哪兒?」接下來,咱們就來添加球體。

建立球體

let earth;
const earthGeometry = new THREE.SphereGeometry(2, 16, 16);
const earthMaterial = new THREE.MeshBasicMaterial({
    specular: 0x333333,
    shininess: 5,
    map: textureLoader.load("./img/earth_atmos_2048.jpg"),
    specularMap: textureLoader.load("./img/earth_specular_2048.jpg"),
    normalMap: textureLoader.load("./img/earth_normal_2048.jpg"),
    normalScale: new THREE.Vector2(0.85, 0.85),
});
earth = new THREE.Mesh(earthGeometry, earthMaterial);
scene.add(earth);
// controls
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.minDistance = 5;
controls.maxDistance = 100;
controls.enablePan = false;

要建立一個球體,咱們須要一個SphereGeometry(球緩衝幾何體)對象. 這個對象該幾何體是經過掃描並計算圍繞着Y軸(水平掃描)和X軸(垂直掃描)的頂點來建立的

接下來,對於這個球體,咱們須要給它一個材質,並加入圖片。Three.js自帶了幾種材質,在這裏咱們使用的是MeshBasicMaterial。若是須要一些光照和物理材質可使用MeshPhysicalMaterial

第三步,咱們須要一個Mesh(網格)。 網格包含一個幾何體以及做用在此幾何體上的材質,咱們能夠直接將網格對象放入到咱們的場景中,並讓它在場景中自由移動。
第四步,加入控制器,以便咱們能夠拖動選擇球體

渲染場景

如今,若是將以前寫好的代碼複製到HTML文件中,你不會在頁面中看到任何東西。這是由於咱們尚未對它進行真正的渲染。爲此,咱們須要使用一個被叫作「渲染循環」(render loop)或者「動畫循環」(animate loop)的東西

function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}

使球體動起來

在開始以前,若是你已經將上面的代碼寫入到了你所建立的文件中,你能夠看到一個地球。讓咱們來作一些更加有趣的事 —— 讓它旋轉起來。

將下列代碼添加到animate()函數中renderer.render調用的上方:

earth.rotation.x += 0.001;
  earth.rotation.y += 0.001;

這段代碼每幀都會執行(正常狀況下是60次/秒),這就讓球體有了一個看起來很不錯的旋轉動畫。基本上來講,當應用程序運行時,若是你想要移動或者改變任何場景中的東西,都必需要通過這個動畫循環。固然,你能夠在這個動畫循環裏調用別的函數,這樣你就不會寫出有上百行代碼的animate函數。

加入背景圖像

//加載背景紋理
var texture = textureLoader.load("./img/eQ9y7xBeY4.jpg");
scene.background = texture;

這樣咱們就實現了一個基於圖片覆蓋的旋轉球體
完整代碼codesandbox
完整代碼gitee
預覽地址
備用預覽地址

相關文章
相關標籤/搜索