欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

js滚动条过渡_如何使用现象在滚动条上创建平滑的WebGL过渡

程序员文章站 2024-03-01 14:21:58
...
js滚动条过渡_如何使用现象在滚动条上创建平滑的WebGL过渡

js滚动条过渡

js滚动条过渡_如何使用现象在滚动条上创建平滑的WebGL过渡

This tutorial is going to demonstrate how to create a smooth WebGL transition on scroll using Phenomenon (based on three.js).

本教程将演示如何使用现象(基于three.js)在滚动上创建平滑的WebGL过渡。

Attention: This tutorial assumes you already have some understanding of how three.js works. 注意:本教程假定您已经对Three.js的工作原理有所了解。
If you are not familiar, I highly recommend checking out the official
如果您不熟悉,我强烈建议您查看官方 documentation and 文档examples . 示例

让我们开始吧 (Let’s get started)

Interactive elements on websites can enhance the user experience a lot. In the demo, a mix of WebGL and regular UI elements will transition based on the scroll position.

网站上的互动元素可以极大地改善用户体验。 在演示中,将基于滚动位置转换WebGL和常规UI元素的混合。

The following libraries are used for this demo:

以下库用于此演示:

  • Three.js: Provides the structure for everything in the WebGL environment.

    Three.js :提供WebGL环境中所有内容的结构。

  • THREE.Phenomenon: Makes it easy to create an instanced mesh that can be transitioned smoothly.

    THREE.Phenomenon :轻松创建可以平滑过渡的实例化网格。

  • updateOnScroll: Observes scroll position changes based on percentage values.

    updateOnScroll :观察基于百分比值的滚动位置更改。

关于现象 (About Phenomenon)

Phenomenon is a small wrapper around three.js built for high-performance WebGL experiences. It started out as a no-dependency library that I created to learn more about WebGL and was later made compatible with the powerful features of three.js.

现象是为高性能WebGL体验而构建的Three.js的小型包装。 它起初是一个无依赖库,我创建该库是为了了解更多有关WebGL的信息,后来使它与three.js的强大功能兼容。

With Phenomenon it’s possible to transition thousands of objects in 3D space in a smooth way. This is done by combining all the separate objects as one. The objects will share the same logic but can move or scale or look different based on unique attributes. To make the experience as smooth as possible it’s important to make it run almost entirely on the GPU. This technique will be explained further below.

借助现象,可以平滑地在3D空间中转换成千上万个对象。 这是通过将所有单独的对象组合为一个对象来完成的。 这些对象将共享相同的逻辑,但可以根据唯一属性移动或缩放或看起来不同。 为了使体验尽可能流畅,重要的是使其几乎完全在GPU上运行。 该技术将在下面进一步说明。

动画实例 (Animate an instance)

To create the animated instances in the demo there are a few steps we need to go through.

要在演示中创建动画实例,我们需要完成几个步骤。

提供基本属性 (Provide base properties)

Define what Geometry to multiply:

定义要相乘的几何

const geometry = new THREE.IcosahedronGeometry(1, 0);

Define how many of objects we want to combine:

定义我们要合并的对象数:

const multiplier = 200;

Define what Material it should have:

定义应具有的材料

const material = new THREE.MeshPhongMaterial({
  color: '#448aff',
  emissive: '#448aff',
  specular: '#efefef',
  shininess: 20,
  flatShading: true,
});

Here we only define the behavior for a single instance. To add to this experience you can add more objects, add lights and shadow or even post processing. Have a look at the Three.js documentation for more information.

在这里,我们仅定义单个实例的行为。 为了增加这种体验,您可以添加更多对象,添加灯光和阴影甚至进行后期处理。 请查看Three.js文档以获取更多信息。

建立过渡 (Build the transition)

The transition of the instance is a little more complex as we will write a vertex shader that will later be combined with our base properties. For this example, we’ll start by moving the objects from point A to point B.

实例的过渡要复杂一些,因为我们将编写一个顶点着色器,该着色器随后将与我们的基本属性结合在一起。 在此示例中,我们将从将对象从点A移动到点B开始。

We can define these points through attributes which are stored directly on the GPU (for every object) and can be accessed from our program. In Phenomenon these attributes are defined with a name so we can use it in our shader and a data function which can provide a unique value for every object.

我们可以通过属性定义这些点,这些属性直接存储在GPU中(对于每个对象),并且可以从我们的程序中访问。 在现象中,这些属性是用名称定义的,因此我们可以在着色器中使用它,并使用一个数据函数为每个对象提供唯一的值。

The code below will define a start- and end position between -10 and 10 for every instance randomly.

下面的代码将为每个实例随机定义介于-10和10之间的开始和结束位置。

function r(v) {
  return -v + Math.random() * v * 2;
}

const attributes = [
  {
    name: 'aPositionStart',
    data: () => [r(10), r(10), r(10)},
    size: 3,
  },
  {
    name: 'aPositionEnd',
    data: () => [r(10), r(10), r(10)]
    size: 3,
  },
];

After all of the objects have a unique start and end position we’ll need a progress value to transition between them. This variable is a uniform that is updated at any time from our main script (for example based on scroll or time).

在所有对象都具有唯一的开始和结束位置之后,我们需要一个进度值才能在它们之间进行转换。 此变量是一个统一变量,可随时从我们的主脚本中进行更新(例如,基于滚动或时间)。

const uniforms = {
  progress: {
    value: 0,
  },
};

Once this is in place the only thing left for us is writing the vertex shader, which isn’t our familiar Javascript syntax, but instead GLSL. We’ll keep it simple for the example to explain the concept, but if you’re interested you can check out the more complex source.

一旦设置好,剩下的就是编写顶点着色器,这不是我们熟悉的Javascript语法,而是GLSL。 我们将通过简单的示例来解释该概念,但是如果您有兴趣,可以查看更复杂的资源。

In the vertex shader a `gl_Position` should be set that will define where every point in our 3d space is located. Based on these positions we can also move, rotate, ease or scale every object separately.

在顶点着色器中,应设置“ gl_Position”,以定义3d空间中每个点的位置。 根据这些位置,我们还可以分别移动,旋转,缓动或缩放每个对象。

Below we define our two position attributes, the progress uniform, and the required main function. In this case, we mix the positions together with the progress which will let the instances move around.

在下面,我们定义了两个位置属性,进度制服和所需的主要功能。 在这种情况下,我们将位置与进度混合在一起,使实例可以移动。

attribute vec3 aPositionStart;
attribute vec3 aPositionEnd;
uniform float progress;

void main(){
  gl_Position = position + mix(aPositionStart, aPositionEnd, progress);
}

The position value is defined in the core of three.js and is based on the selected geometry.

位置值在three.js的核心中定义,并且基于所选的几何形状。

滚动过渡 (Transition on scroll)

When we put all the above code together and give each instance a slight offset (so they move after each other) we can start updating our progress based on the scroll position.

当我们将以上所有代码放在一起并给每个实例一个微小的偏移量(以便它们彼此移动)时,我们可以开始基于滚动位置更新进度。

With the updateOnScroll library we can easily observe the scroll position based on percentage values. In the example below a value of 0 to 1 is returned between 0% and 50% of the total scroll height. By setting the progress uniform to that value our interaction will be connected to the transition in WebGL!

使用updateOnScroll库,我们可以轻松地基于百分比值观察滚动位置。 在下面的示例中,返回值0到1在总滚动高度的0%到50%之间。 通过将进度统一设置为该值,我们的交互将连接到WebGL中的过渡!

const phenomenon = new THREE.Phenomenon({ ... });

updateOnScroll(0, 0.5, progress => {
 phenomenon.uniforms.progress.value = progress;
});

In the demo every instance (and the UI elements in between) have their own scroll handler (based on a single listener).

在演示中,每个实例(及其之间的UI元素)都有自己的滚动处理程序(基于单个侦听器)。

下一步 (Next steps)

With all of the above combined our experience is off to a great start, but there’s a lot more we can do:

结合以上所有内容,我们的经验是一个良好的开端,但我们还有很多工作要做:

  • Add color, lights and custom material

    添加颜色,灯光和自定义材质
  • Add more types user interaction

    添加更多类型的用户互动
  • Transition with easing

    轻松过渡
  • Transition scale or rotation

    过渡尺度或旋转
  • Transition based on noise

    基于噪声的过渡

Have a look at the WebGL Wonderland collection for multiple experiments showcasing the possibilities!

看一下WebGL Wonderland集合,进行多个实验,展示各种可能性!

js滚动条过渡_如何使用现象在滚动条上创建平滑的WebGL过渡

结论 (Conclusion)

Learning about WebGL has been an interesting journey for me and I hope this tutorial has inspired you!

对我而言,学习WebGL经历了一段有趣的旅程,希望本教程对您有所启发!

Feel free to ask questions or share experiments that you’ve created, thank you for reading! ????

随时提出问题或分享您创建的实验,感谢您的阅读! ????

翻译自: https://tympanus.net/codrops/2019/03/22/how-to-create-smooth-webgl-transitions-on-scroll-using-phenomenon/

js滚动条过渡