Three.js实现一个动态的 3D 点阵波浪效果

news2025/2/11 0:29:37

        使用 Three.js 创建了一个动态的 3D 点阵波浪效果,可用作页面背景。它通过粒子系统生成点阵,并根据鼠标移动和时间动态调整点的位置和大小,形成波浪效果。用户可以通过组件的 props 控制波浪的长度、颜色和位置。

<template>
  <div id="iviewBg"></div>
</template>
  
<script>
  import * as THREE from "three";
  const SEPARATION = 100;
  
  export default {
    name: 'PointsWaves',
    props: {
      //控制x轴波浪的长度
      amountX: {
        type: Number,
        default: 50,
      },
      //控制y轴波浪的长度
      amountY: {
        type: Number,
        default: 50,
      },
      //控制点颜色
      color: {
        type: String,
        default: "#8a8a8a",
      },
      //控制波浪的位置
      top: {
        type: Number,
        default: 350,
      },
    },
    data() {
      return {
        container: null,
        camera: null,
        scene: null,
        renderer: null,
        particles: null,
        count: 0,
        mouseX: 0,
        windowHalfX: 0,
      };
    },
    mounted() {
      this.windowHalfX = window.innerWidth / 2;
      this.init();
      this.animate();
    },
    methods: {
      init() {
        this.container = document.createElement("div");
        document.getElementById("iviewBg").appendChild(this.container);
  
        //创建透视相机
        this.camera = new THREE.PerspectiveCamera(
          55, //摄像机视锥体垂直视野角度
          window.innerWidth / window.innerHeight, //摄像机视锥体长宽比
          1, //摄像机视锥体近端面
          10000 //摄像机视锥体远端面
        );
  
        //设置相机z轴视野
        this.camera.position.z = 1000;
  
        //创建场景
        this.scene = new THREE.Scene();
  
        const numParticles = this.amountX * this.amountY;
  
        const positions = new Float32Array(numParticles * 3);
        const scales = new Float32Array(numParticles);
  
        let i = 0,
          j = 0;
  
        // 初始化粒子位置和大小
        for (let ix = 0; ix < this.amountX; ix++) {
          for (let iy = 0; iy < this.amountY; iy++) {
            positions[i] = ix * SEPARATION - (this.amountX * SEPARATION) / 2; // x
            positions[i + 1] = 0; // y
            positions[i + 2] = iy * SEPARATION - (this.amountY * SEPARATION) / 2; // z
            scales[j] = 1;
            i += 3;
            j++;
          }
        }
  
        //是面片、线或点几何体的有效表述。包括顶点位置,面片索引、法相量、颜色值、UV 坐标和自定义缓存属性值。使用 BufferGeometry 可以有效减少向 GPU 传输上述数据所需的开销
        const geometry = new THREE.BufferGeometry();
        geometry.setAttribute(
          "position",
          new THREE.BufferAttribute(positions, 3)
        );
        geometry.setAttribute("scale", new THREE.BufferAttribute(scales, 1));
  
        //着色器材质(ShaderMaterial),设置球的大小,颜色,等
        const material = new THREE.ShaderMaterial({
          uniforms: {
            //设置球的颜色
            color: { value: new THREE.Color(this.color) },
          },
          //控制球的大小
          vertexShader:
            "attribute float scale; void main() {vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );gl_PointSize = scale * ( 300.0 / - mvPosition.z );gl_Position = projectionMatrix * mvPosition;}",
          fragmentShader:
            "uniform vec3 color;void main() {if ( length( gl_PointCoord - vec2( 0.5, 0.5 ) ) > 0.475 ) discard;gl_FragColor = vec4( color, 1.0 );}",
        });
  
        //一个用于显示点的类。
        this.particles = new THREE.Points(geometry, material);
        //往场景中添加点
        this.scene.add(this.particles);
  
        //alpha - canvas是否包含alpha (透明度)。默认为 false。
        //渲染器的背景色默认为黑色,设置渲染器的背景色为透明
        this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
        this.renderer.setPixelRatio(window.devicePixelRatio);
        this.renderer.setClearAlpha(0);
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        this.container.appendChild(this.renderer.domElement);
  
        //显示右上角fps框
        // stats = new Stats();
        //   container.appendChild(stats.dom);
  
        this.container.style.touchAction = "none";
        //监听鼠标移动事件
        this.container.addEventListener("pointermove", this.onPointerMove);
  
        //调整波浪的位置
        this.container.style.position = "relative";
        this.container.style.top = `${this.top}px`;
  
        window.addEventListener("resize", this.onWindowResize);
      },
      render() {
        this.camera.position.x += (this.mouseX - this.camera.position.x) * 0.05;
        this.camera.position.y = 400;
        this.camera.lookAt(this.scene.position);
  
        const positions = this.particles.geometry.attributes.position.array;
        const scales = this.particles.geometry.attributes.scale.array;
  
        // 设置粒子位置和大小
        let i = 0,
          j = 0;
        for (let ix = 0; ix < this.amountX; ix++) {
          for (let iy = 0; iy < this.amountY; iy++) {
            positions[i + 1] =
              Math.sin((ix + this.count) * 0.3) * 50 +
              Math.sin((iy + this.count) * 0.5) * 50;
  
            scales[j] =
              (Math.sin((ix + this.count) * 0.3) + 1) * 10 +
              (Math.sin((iy + this.count) * 0.5) + 1) * 10;
  
            i += 3;
            j++;
          }
        }
  
        this.particles.geometry.attributes.position.needsUpdate = true;
        this.particles.geometry.attributes.scale.needsUpdate = true;
  
        this.renderer.render(this.scene, this.camera);
  
        this.count += 0.1;
      },
      onWindowResize() {
        this.windowHalfX = window.innerWidth / 2;
        this.camera.aspect = window.innerWidth / window.innerHeight;
        this.camera.updateProjectionMatrix();
        this.renderer.setSize(window.innerWidth, window.innerHeight);
      },
      onPointerMove(event) {
        //console.log(event);
        if (event.isPrimary === false) return;
        this.mouseX = event.clientX - this.windowHalfX;
      },
      animate() {
        requestAnimationFrame(this.animate);
        this.render();
        //fps 实时更新
        // stats.update();
      },
    },
  };
</script>
  
<style scoped>
  #iviewBg {
    width: 100vw;
    height: 100vh;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    text-align: center;
    overflow: hidden;
  }
</style>
  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2295308.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【韩顺平linux】部分上课笔记整理

整理一下一些韩顺平老师上课时候的笔记 课程&#xff1a;【小白入门 通俗易懂】韩顺平 一周学会Linux linux环境&#xff1a;使用阿里云服务器 笔记参考 &#xff1a; [学习笔记]2021韩顺平一周学会Linux 一、自定义函数 基本语法 应用实例&#xff1a; 计算两个参数的和…

CPP集群聊天服务器开发实践(一):用户注册与登录

目录 1 客户端用户注册与登录 1.1 主要思想 1.2 网络层 1.3 业务层 1.4 数据层 1.5 测试结果 1 客户端用户注册与登录 1.1 主要思想 实现网络层、业务层、数据层的解耦&#xff0c;提高系统的可维护性。 网络层&#xff1a;主要实现对客户端连接、客户端读写请求的捕获…

学JDBC 第二日

数据库连接池 作用 使数据库连接达到重用的效果&#xff0c;较少的消耗资源 原理 在创建连接池对象时&#xff0c;创建好指定个数的连接对象 之后直接获取连接对象使用即可&#xff0c;不用每次都创建连接对象 从数据库连接池中获取的对象的close方法真的关闭连接对象了吗…

【Uniapp-Vue3】z-paging插件组件实现触底和下拉加载数据

一、下载z-paing插件 注意下载下载量最多的这个 进入Hbuilder以后点击“确定” 插件的官方文档地址&#xff1a; https://z-paging.zxlee.cn 二、z-paging插件的使用 在文档中向下滑动&#xff0c;会有使用方法。 使用z-paging标签将所有的内容包起来 配置标签中的属性 在s…

【C语言标准库函数】三角函数

目录 一、头文件 二、函数简介 2.1. 正弦函数&#xff1a;sin(double angle) 2.2. 余弦函数&#xff1a;cos(double angle) 2.3. 正切函数&#xff1a;tan(double angle) 2.4. 反正弦函数&#xff1a;asin(double value) 2.5. 反余弦函数&#xff1a;acos(double value)…

Redisson全面解析:从使用方法到工作原理的深度探索

文章目录 写在文章开头详解Redisson基本数据类型基础配置字符串操作列表操作映射集阻塞队列延迟队列更多关于Redisson详解Redisson 中的原子类详解redisson中的发布订阅模型小结参考写在文章开头 Redisson是基于原生redis操作指令上进一步的封装,屏蔽了redis数据结构的实现细…

声明式导航,编程式导航,导航传参,下拉刷新

1.页面导航 1.声明式导航 1.1跳转到tabBar页面 1.2跳转到非tabBar页面 1.2后退导航 、 2.编程式导航 2.1跳转到tabBar页面 2.1跳转到非tabBar页面 2.3后退导航 3.导航传参 3.1声名式导航传参 3.2编程式导航传参 3.3在onLoad中接受参数 4.下拉刷新 4.1回顾下拉刷新…

金和OA C6 DownLoadBgImage任意文件读取漏洞

金和OA C6 DownLoadBgImage任意文件读取漏洞 漏洞描述 金和C6数据库是一款针对企业信息化管理而设计的高级数据库管理系统&#xff0c;主要应用于企业资源规划&#xff08;ERP&#xff09;、客户关系管理&#xff08;CRM&#xff09;以及办公自动化&#xff08;OA&#xff09…

激活函数篇 03 —— ReLU、LeakyReLU、ELU

本篇文章收录于专栏【机器学习】 以下是激活函数系列的相关的所有内容: 一文搞懂激活函数在神经网络中的关键作用 逻辑回归&#xff1a;Sigmoid函数在分类问题中的应用 整流线性单位函数&#xff08;Rectified Linear Unit, ReLU&#xff09;&#xff0c;又称修正线性单元&a…

Kafka 入门与实战

一、Kafka 基础 1.1 创建topic kafka-topics.bat --bootstrap-server localhost:9092 --topic test --create 1.2 查看消费者偏移量位置 kafka-consumer-groups.bat --bootstrap-server localhost:9092 --describe --group test 1.3 消息的生产与发送 #生产者 kafka-cons…

5 计算机网络

5 计算机网络 5.1 OSI/RM七层模型 5.2 TCP/IP协议簇 5.2.1:常见协议基础 一、 TCP是可靠的&#xff0c;效率低的&#xff1b; 1.HTTP协议端口默认80&#xff0c;HTTPSSL之后成为HTTPS协议默认端口443。 2.对于0~1023一般是默认的公共端口不需要注册&#xff0c;1024以后的则需…

VMware虚拟机安装、创建Ubuntu虚拟机及汉化设置全流程详细教程

一、安装VMware Workstation 下载VMware 访问官网&#xff1a;https://www.vmware.com 选择适合的版本&#xff08;如 Workstation Pro 或 VMware Player&#xff0c;后者免费&#xff09;。完成下载后运行安装程序。 网盘下载&#xff1a; 链接: https://pan.baidu.com/s/1MQ…

21.2.7 综合示例

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 【例 21.7】【项目&#xff1a;code21-007】填充职员表并打印。 本例使用到的Excel文件为&#xff1a;职员信息登记表.xlsx&#x…

【大模型】DeepSeek与chatGPT的区别以及自身的优势

目录 一、前言二、核心技术对比2.1 模型架构设计2.1.1 ChatGPT的Transformer架构2.1.2 DeepSeek的混合架构 2.2 训练数据体系2.2.1 ChatGPT的数据特征2.2.2 DeepSeek的数据策略 三、应用场景对比3.1 通用场景表现3.1.1 ChatGPT的强项领域3.2.2 DeepSeek的专项突破 3.3 响应效率…

burpsuite抓取html登陆和上传数据包

一、burpsuite抓取html登陆数据包 1、先写一个html格式的登陆页面 <!doctype html> <html lang"en"> <head><meta charset"UTF-8"><title>这是标签</title></head> <body> <hr><!-- 登陆表单 …

Linux 安装 Ollama

1、下载地址 Download Ollama on Linux 2、有网络直接执行 curl -fsSL https://ollama.com/install.sh | sh 命令 3、下载慢的解决方法 1、curl -fsSL https://ollama.com/install.sh -o ollama_install.sh 2、sed -i s|https://ollama.com/download/ollama-linux|https://…

使用Ollama本地部署deepseek

1、下载安装Ollama 前往下载页面 https://ollama.com/download下载好安装包&#xff0c;如同安装软件一样&#xff0c;直接安装即可 win中默认为C盘&#xff0c;如果需要修改到其他盘&#xff0c;查找具体教程 运行list命令&#xff0c;检查是否安装成功 2、修改模型下载的…

如何在RTACAR中配置IP多播(IP Multicast)

一、什么是IP多播 IP多播&#xff08;IP Multicast&#xff09;是一种允许数据包从单一源地址发送到多个目标地址的技术&#xff0c;是一种高效的数据传输方式。 多播地址是专门用于多播通信的IP地址&#xff0c;范围从 224.0.0.0到239.255.255.255 与单播IP地址不同&#x…

2025年最新版武书连SCD期刊(中国科学引文数据库)来源期刊已更新,可下载PDF版!需要的作者进来了解~

2025年最新版武书连SCD期刊&#xff08;中国科学引文数据库&#xff09;来源期刊已更新&#xff01; 官网是不提供免费查询的。小编给大家两个路径&#xff0c;无需下载PDF&#xff0c;随时随地都能查25版SCD目录。 路径一&#xff1a;中州期刊联盟官网&#xff0c;25版SCD目…

存储异常导致的Oracle重大生产故障

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验 Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、MySQL、PG、高斯…