当前位置:主页 > 查看内容

前端如何实现一个图片覆盖的球体

发布时间:2021-07-02 00:00| 位朋友查看

简介:简介 做展示类项目的时候,通常要实现一些圆形选择的效果。这个借助 css 的 rotate 就可以实现.但是!要实现一个 3D 的带图片的旋转球体该怎么做呢?让我们开始吧。 完整代码codesandbox?? 完整代码gitee?? 预览地址?? 备用预览地址?? 工具 three.js OrbitCo……

earth_atmos_2048.jpg

简介

做展示类项目的时候,通常要实现一些圆形选择的效果。这个借助cssrotate 就可以实现.但是!要实现一个3D的带图片的旋转球体该怎么做呢?让我们开始吧。

完整代码codesandbox??
完整代码gitee??
预览地址??
备用预览地址??

工具

three.js
OrbitControls

绘制

创建一个场景

将场景借助three.js来进行显示,我们需要以下几个对象:场景、相机和渲染器,这样我们就能透过摄像机渲染出场景。

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);

我们花一点点时间来解释一下这里发生了什么。我们现在建立了场景、相机和渲染器。

three.js里有几种不同的相机,在这里,我们使用的是PerspectiveCamera(透视摄像机)。

第一个参数是视野角度(FOV)。视野角度就是无论在什么时候,你所能在显示器上看到的场景的范围,数值越大越远。

第二个参数是长宽比(aspect ratio)。 也就是你用一个物体的宽除以它的高的值。比如说,当你在一个宽屏电视上播放老电影时,可以看到图像仿佛是被压扁的。

接下来的两个参数是近截面(near)和远截面(far)。 当物体某些部分比摄像机的远截面远或者比近截面近的时候,该这些部分将不会被渲染到场景中。或许现在你不用担心这个值的影响,但未来为了获得更好的渲染性能,你将可以在你的应用程序里去设置它。

接下来是渲染器。这里是施展魔法的地方。除了我们在这里用到的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;

这样我们就实现了一个基于图片覆盖的旋转球体

结尾

喜欢的话就点个赞吧
更多问题欢迎加入前端交流群交流749539640
完整代码codesandbox??
完整代码gitee??
预览地址??
备用预览地址??


本文转自网络,版权归原作者所有,原文链接:https://segmentfault.com/a/1190000040274437
本站部分内容转载于网络,版权归原作者所有,转载之目的在于传播更多优秀技术内容,如有侵权请联系QQ/微信:153890879删除,谢谢!

推荐图文


随机推荐