关键词

threeJs实现波纹扩散及光标浮动效果详解

Three.js实现波纹扩散及光标浮动效果详解

概述

本教程将介绍如何使用Three.js库实现波纹扩散效果及光标浮动效果。波纹扩散效果常见于网页设计中,而光标浮动效果则经常出现在用户交互的UI设计中。

本文主要分为以下三个部分:

  1. 前置知识
  2. 波纹扩散效果实现
  3. 光标浮动效果实现

本文中的所有代码都可在 codepen 中找到。

一、前置知识

要实现本教程中的效果,需要有一定的WebGL以及Three.js基础。

如果你需要进行回顾或学习,可以看看 Three.js官方文档 或者 WebGL Fundamentals

二、波纹扩散效果实现

下面将详细介绍如何使用Three.js库实现波纹扩散效果。

1. 创建场景

在 HTML 中创建一个容器(例如一个div标签),并指定其宽度和高度,作为Three.js场景的载体。

<div id="canvas-container"></div>

在 JS 中,使用 THREE 对象创建场景、相机和渲染器。

const container = document.getElementById('canvas-container');
const renderer = new THREE.WebGLRenderer({ antialias: true });
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);

renderer.setSize(container.offsetWidth, container.offsetHeight);
container.appendChild(renderer.domElement);

camera.position.z = 10;

2. 创建网格

使用 Three.js 中的 Mesh 类创建一个平面网格,作为波纹的扩散面。

const geometry = new THREE.PlaneBufferGeometry(10, 10, 500, 500);
const material = new THREE.MeshBasicMaterial({ color: 0x7ec0ee });
const mesh = new THREE.Mesh(geometry, material);

scene.add(mesh);

3. 实现shader

在Three.js的材质中,使用自定义的着色器代码是可以实现更加复杂的视觉效果的。这里,我们需要实现一个实时扩散波纹的着色器。

首先,在 HTML 文件中添加一个代表着色器的script标签。

<script type="x-shader/x-vertex" id="vertexShader">
  void main() {
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
  }
</script>
<script type="x-shader/x-fragment" id="fragmentShader">
  uniform float time;
  uniform vec2 resolution;

  const float speed = 0.1;
  const float frequency = 30.0;

  void main() {
    vec2 uv = gl_FragCoord.xy / resolution.xy;
    vec2 o = vec2(0.5, 0.5);
    vec2 ref = vec2(0.5, 0.5);
    float dist = distance(ref, uv);
    float radius = smoothstep(0.15, 0.51, fract(time * speed));

    gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0) * (1.0 - smoothstep(radius, radius + 0.005, dist));
  }
</script>

着色器代码中,我们用了两个 uniform 变量,time 和 resolution。

这里的time变量代表当前的时间,它在每帧渲染时都会更新。

$resolution$ 是屏幕尺寸,我们把它传入到着色器中作为一个uniform变量。

界面的波纹扩散效果通过改变radius来实现。从代码中你可以看到,radius的值由一个smoothstep函数产生。当时间增加时,参数x对应的值将从0到1变化,而smoothstep(x, y, a)返回一个在x和y之间的a的平滑插值,使得x到y之间的变化更加平稳。

最后,我们需要把着色器代码编译成 THREE.ShaderMaterial() 来使用。

const vertexShader = document.getElementById('vertexShader').textContent;
const fragmentShader = document.getElementById('fragmentShader').textContent;

const uniforms = {
  time: { value: 0 },
  resolution: { value: new THREE.Vector2(container.offsetWidth, container.offsetHeight) },
};
const material = new THREE.ShaderMaterial({
  uniforms,
  vertexShader,
  fragmentShader,
});

mesh.material = material;

4. 实现动画

最后,我们需要在每一帧中更新 uniforms 中的 time,以便在材料中使用。

function animate() {
  requestAnimationFrame(animate);

  mesh.material.uniforms.time.value = performance.now() / 1000;

  renderer.render(scene, camera);
}

animate();

三、光标浮动效果实现

下面将详细介绍如何使用Three.js库实现光标浮动效果。

1. 创建场景

和上面的步骤一致,我们需要在 HTML 中创建一个容器以及在 JS 中创建一个场景、相机和渲染器。

const container = document.getElementById('canvas-container');
const renderer = new THREE.WebGLRenderer({ antialias: true });
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);

renderer.setSize(container.offsetWidth, container.offsetHeight);
container.appendChild(renderer.domElement);

camera.position.z = 10;

2. 添加网格

使用 Three.js 中的 Mesh 类创建一个浮动网格,作为光标的浮动面。

const geometry = new THREE.PlaneBufferGeometry(1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0xffffff });
const mesh = new THREE.Mesh(geometry, material);

scene.add(mesh);

3. 实现鼠标跟踪

当鼠标移动时,我们需要把单击位置转换成屏幕空间坐标。此时需要使用 THREE.Vector2()THREE.Raycaster()

const mouse = new THREE.Vector2();
const raycaster = new THREE.Raycaster();

container.addEventListener('mousemove', onDocumentMouseMove, false);

function onDocumentMouseMove(event) {
  mouse.x = (event.clientX / container.offsetWidth) * 2 - 1;
  mouse.y = - (event.clientY / container.offsetHeight) * 2 + 1;
}

4. 实现动画

最后,我们需要在每一帧中更新网格的位置,使其跟随鼠标移动。

function animate() {
  requestAnimationFrame(animate);

  mesh.position.x += (mouse.x * 10 - mesh.position.x) * 0.1;
  mesh.position.y += (mouse.y * 10 - mesh.position.y) * 0.1;

  renderer.render(scene, camera);
}

animate();

结论

到这里,我们已经成功实现了波纹扩散效果和光标浮动效果。

以上代码也可在 codepen 中找到,并可以进行自由修改和运行。

本文链接:http://task.lmcjl.com/news/11498.html

展开阅读全文