了解如何使用Three.js为图像网格创建缩略图到全屏动画。
动画在用户对您网站的感受方面发挥着重要作用。它们传达了您网站的许多个性和感觉。它们还可以帮助用户更轻松地浏览新的和已知的屏幕。
在本教程中,我们想了解如何在图像上创建一些有趣的网格到全屏动画。我们的想法是拥有一个较小图像的网格,当点击一个图像时,图像会以特殊动画进行放大以覆盖整个屏幕。我们的目标是使它们易于使用,独特且具有视觉吸引力。此外,我们希望向您展示制作自己的步骤。
积木
在我们开始做各种疯狂的动画,计时计算和现实变形之前,我们需要准备好效果的基本设置:
- 初始化Three.js和我们将使用的飞机
- 定位和缩放平面,使其与用户单击项目时的项目图像类似
- 为平面设置动画,使其覆盖整个屏幕
为了不会因为我们可以制作的所有效果而过于疯狂,我们将专注于制作像我们的第一个演示中那样的翻转效果。
初始化
首先,让我们进行一个基本的Three.js设置并添加一个1×1平面,我们将重新使用这个平面用于每个网格项目的动画。因为当时只能有一个动画发生。通过仅为所有动画使用一个平面,我们可以获得更好的性能。
这个简单的更改将允许我们拥有任意数量的HTML项目,而不会影响动画的性能。
作为旁注,在我们的方法中,我们决定仅在动画时使用Three.js。这意味着所有项目都是很好的旧HTML。
这使得我们的代码可以为没有WebGL支持的浏览器提供自然的回退。它也使我们的效果更容易获得。
class GridToFullscreenEffect {
...
init(){
...
const segments = 128;
var geometry = new THREE.PlaneBufferGeometry(1, 1, segments, segments);
// We'll be using the shader material later on ;)
var material = new THREE.ShaderMaterial({
side: THREE.DoubleSide
});
this.mesh = new THREE.Mesh(geometry, material);
this.scene.add(this.mesh);
}
}
注意:我们正在跳过Three.js初始化,因为它非常基本。
将平面几何体的大小设置为1×1可以简化一些事情。它删除了计算正确比例所涉及的一些数学运算。由于按任何数字缩放的1总是会返回相同的数字。
定位和调整大小
现在,我们将调整大小并定位飞机以匹配项目的图像。要做到这一点,我们需要获得该项目getBoundingClientRect
。然后我们需要将其值从像素转换为相机的视图单位。之后,我们需要将它们从相对于左上角转换为相对于中心的相对转换。总结如下:
- 将像素单位映射到相机的视图单位
- 使单位相对于中心而不是左上角
- 使位置的原点从平面的中心开始,而不是在左上角
- 使用这些新值缩放和定位网格
class GridToFullscreenEffect { ... onGridImageClick(ev,itemIndex){ // getBoundingClientRect gives pixel units relative to the top left of the pge const rect = ev.target.getBoundingClientRect(); const viewSize = this.getViewSize(); // 1. Transform pixel units to camera's view units const widthViewUnit = (rect.width * viewSize.width) / window.innerWidth; const heightViewUnit = (rect.height * viewSize.height) / window.innerHeight; let xViewUnit = (rect.left * viewSize.width) / window.innerWidth; let yViewUnit = (rect.top * viewSize.height) / window.innerHeight; // 2. Make units relative to center instead of the top left. xViewUnit = xViewUnit - viewSize.width / 2; yViewUnit = yViewUnit - viewSize.height / 2; // 3. Make the origin of the plane's position to be the center instead of top Left. let x = xViewUnit + widthViewUnit / 2; let y = -yViewUnit - heightViewUnit / 2; // 4. Scale and position mesh const mesh = this.mesh; // Since the geometry's size is 1. The scale is equivalent to the size. mesh.scale.x = widthViewUnit; mesh.scale.y = heightViewUnit; mesh.position.x = x; mesh.position.y = y; } }