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

yizhihongxing

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 中找到,并可以进行自由修改和运行。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:threeJs实现波纹扩散及光标浮动效果详解 - Python技术站

(0)
上一篇 2023年6月11日
下一篇 2023年6月11日

相关文章

  • js对象浅拷贝和深拷贝详解

    JS对象浅拷贝和深拷贝详解 在JavaScript中,对象是非常重要的数据类型,它允许我们用键值对的形式来表示和存储数据。当我们需要复制一个对象时,需要了解什么是浅拷贝和什么是深拷贝。本文将详细解释这两种拷贝方式,并提供实例进行说明。 什么是浅拷贝 浅拷贝是指复制出来的新对象的属性是源对象的引用,而不是属性值的拷贝。也就是说,当源对象属性的值为对象或数组时,…

    JavaScript 2023年5月27日
    00
  • js自执行函数的几种不同写法的比较

    让我们来详细讲解一下“js自执行函数的几种不同写法的比较”。 什么是自执行函数? 自执行函数,也被称为立即执行函数,是指在定义函数后立即调用该函数的一种方式,通常被用来封装一些特定的操作,避免变量污染全局作用域。 自执行函数的几种不同写法 写法一:使用小括号将函数包裹起来 (function () { // code goes here })(); // 或…

    JavaScript 2023年5月27日
    00
  • DOM节点深度克隆函数cloneNode()用法实例

    DOM节点深度克隆函数cloneNode()是一个非常常用的方法,可用于将当前节点的所有子孙节点以及属性克隆到新节点中。本文将详细介绍cloneNode()的用法,包括如何使用该方法创建克隆节点、如何克隆节点的所有子元素以及如何实现深拷贝等。 克隆节点 首先我们来看如何使用cloneNode()方法创建克隆节点。cloneNode()方法可以接收一个参数,表…

    JavaScript 2023年6月10日
    00
  • Ajax请求WebService跨域问题的解决方案

    跨域即浏览器从一个域名的网页,向另一个域名的服务器请求数据,因为同源策略的限制,Ajax请求WebService跨域通常会出现问题。那么如何解决这个问题呢?下面是一种常见的解决方案: 方案一:Jsonp跨域 JSONP(JSON with Padding)是 JSON 的一种“使用模式”,可用于解决跨域问题。JSONP 的原理是通过 标签的 src 属性不受…

    JavaScript 2023年6月11日
    00
  • 浅析javascript的return语句

    浅析JavaScript的return语句,我们可以从以下几个方面进行阐述: 1. return的作用 在函数内,return关键字的作用是“终止函数执行并返回一个值”。也就是说,当函数执行到return语句时,会立即退出函数并返回一个值,如果没有指定返回值,则返回undefined。 2. return的使用方式 在JavaScript中,return的使…

    JavaScript 2023年6月10日
    00
  • 使用3D引擎threeJS实现星空粒子移动效果

    使用3D引擎threeJS实现星空粒子移动效果的完整攻略包含以下几个步骤: 步骤一:引入three.js 首先需要在代码中引入three.js这个库,代码如下: <script src="https://cdn.bootcdn.net/ajax/libs/three.js/105/three.min.js"></scri…

    JavaScript 2023年6月11日
    00
  • loading动画特效小结

    这里是“loading动画特效小结”的完整攻略: loading动画特效小结 1. 为什么需要loading动画 在网页加载的过程中,用户等待时间过长往往会让用户们感到烦躁,而且这个等待时间也是会让用户选择放弃等待,选择离开的!而为了避免这个情况产生,我们需要添加页面加载动画,以方便用户等待。 2. 实现loading动画的方法 实现loading动画有多种…

    JavaScript 2023年6月10日
    00
  • 收集的比较全的automation服务器不能创建对象 异常原因和解决方法第1/2页

    收集的比较全的automation服务器不能创建对象 异常原因和解决方法 问题描述 当在使用Automation对象时,可能会出现收集的比较全的automation服务器不能创建对象的异常错误。该错误的主要描述是无法创建对象,在使用Automation时会造成很大的困扰。 异常原因 这个问题通常是由以下原因引起的: COM组件注册问题。如果组件没有正确注册或…

    JavaScript 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部