基于three.js生成动态波浪背景效果

文章目录

  • 前言
  • 一、安装three
  • 二、新建waves.js文件
  • 三、引入waves.js文件比查看效果
    • `如有启发,可点赞收藏哟~`


前言

基于three.js生成动态波浪背景效果
在这里插入图片描述


一、安装three

npm i three -S

二、新建waves.js文件

注意geometry.setAttributegeometry.addAttribute和在不同版本会报错,切换其他一个即可兼容

import * as THREE from 'three';

var SEPARATION = 100,
  AMOUNTX = 50,
  AMOUNTY = 50;
var container;
var camera, scene, renderer;
var particles,
  count = 0;
var mouseX = 0,
  mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;

function init(id) {
  container = document.querySelector('#' + id) || document.createElement('div');
  camera = new THREE.PerspectiveCamera(100, window.innerWidth / window.innerHeight, 1, 10000);
  camera.position.y = 600;
  camera.position.z = 1200;
  scene = new THREE.Scene();
  //
  var numParticles = AMOUNTX * AMOUNTY;
  var positions = new Float32Array(numParticles * 3);
  var scales = new Float32Array(numParticles);
  var i = 0,
    j = 0;
  for (var ix = 0; ix < AMOUNTX; ix++) {
    for (var iy = 0; iy < AMOUNTY; iy++) {
      positions[i] = ix * SEPARATION - (AMOUNTX * SEPARATION) / 2; // x
      positions[i + 1] = 0; // y
      positions[i + 2] = iy * SEPARATION - (AMOUNTY * SEPARATION) / 2; // z
      scales[j] = 1;
      i += 3;
      j++;
    }
  }
  var geometry = new THREE.BufferGeometry();
  console.log('geometry_geometry', geometry)
  geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
  geometry.setAttribute('scale', new THREE.BufferAttribute(scales, 1));
  var material = new THREE.ShaderMaterial({
    uniforms: {
      color: { value: new THREE.Color('rgb(182, 232, 255)') },
    },
    // vertexShader: document.getElementById('vertexshader').textContent,
    // fragmentShader: document.getElementById('fragmentshader').textContent,
    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 );
      }`,
    alphaTest: 0.5,
  });
  //
  particles = new THREE.Points(geometry, material);
  scene.add(particles);
  //
  renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight >> 1);
  container.appendChild(renderer.domElement);

  document.addEventListener('mousemove', onDocumentMouseMove, false);
  document.addEventListener('touchstart', onDocumentTouchStart, false);
  document.addEventListener('touchmove', onDocumentTouchMove, false);
  //
  window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
  windowHalfX = window.innerWidth / 2;
  windowHalfY = window.innerHeight / 2;
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight >> 1);
}
//
function onDocumentMouseMove(event) {
  mouseX = event.clientX - windowHalfX;
  mouseY = event.clientY - windowHalfY;
}
function onDocumentTouchStart(event) {
  if (event.touches.length === 1) {
    event.preventDefault();
    mouseX = event.touches[0].pageX - windowHalfX;
    mouseY = event.touches[0].pageY - windowHalfY;
  }
}
function onDocumentTouchMove(event) {
  if (event.touches.length === 1) {
    event.preventDefault();
    mouseX = event.touches[0].pageX - windowHalfX;
    mouseY = event.touches[0].pageY - windowHalfY;
  }
}
//
function animate() {
  requestAnimationFrame(animate);
  render();
}
function render() {
  var cy = (-mouseY - camera.position.y) * 0.01;
  camera.position.x += (mouseX - camera.position.x) * 0.02;
  // camera.position.y += (-mouseY - camera.position.y) * 0.01;
  // camera.position.y += cy < -1 ? -1 : cy;
  camera.lookAt(scene.position);
  var positions = particles.geometry.attributes.position.array;
  var scales = particles.geometry.attributes.scale.array;
  var i = 0,
    j = 0;
  for (var ix = 0; ix < AMOUNTX; ix++) {
    for (var iy = 0; iy < AMOUNTY; iy++) {
      positions[i + 1] = Math.sin((ix + count) * 0.3) * 100 + Math.sin((iy + count) * 0.5) * 100;
      scales[j] = (Math.sin((ix + count) * 0.3) + 1) * 5 + (Math.sin((iy + count) * 0.5) + 1) * 5;
      i += 3;
      j++;
    }
  }
  particles.geometry.attributes.position.needsUpdate = true;
  particles.geometry.attributes.scale.needsUpdate = true;
  renderer.render(scene, camera);
  count += 0.1;
}

export default function threeWaves(id) {
  init(id);
  animate();
}

三、引入waves.js文件比查看效果

  • components/waves/index.vue
<script lang="ts" src="./index.ts" />

<template>
  <div class="login flex-align-center">
    
    <div class="brand-info waves" id="waves-js"></div>
    
    <!-- <script type="x-shader/x-vertex" id="vertexshader">
      attribute float scale;
      void main() {
        vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
        gl_PointSize = scale * ( 300.0 / - mvPosition.z );
        gl_Position = projectionMatrix * mvPosition;
      }
    </script>
    <script type="x-shader/x-fragment" id="fragmentshader">
      uniform vec3 color;
      void main() {
        if ( length( gl_PointCoord - vec2( 0.5, 0.5 ) ) > 0.475 ) discard;
        gl_FragColor = vec4( color, 1.0 );
      }
    </script> -->
    
  </div>
</template>

<style scoped lang="less">
.login {
  width: 100%;
  height: 100%;
  background: @273b84;
  
}
.brand-info {
  color: #fff;
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  background: none;
  background-color: transparent;

  &.particles {
    top: 0;
    z-index: 6
  }

  &.waves {
    height: 50%;
    bottom: 0;
    z-index: 5;
  }
}
</style>

  • components/waves/index.js
import { defineComponent, onMounted } from 'vue'
import threeWaves from '@/assets/libs/waves';

export default defineComponent({
  setup() {
    onMounted(() => {
      threeWaves('waves-js');
    })
    return {
    };
  },
});

效果
在这里插入图片描述


如有启发,可点赞收藏哟~

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【腾讯地图】【微信小程序】地图选点

【相关文章】 【腾讯地图】【微信小程序】地图选点 【腾讯地图】【微信小程序】路线规划 【腾讯地图】【微信小程序】城市记录&#xff08;基于地图选点入门版&#xff09; 【效果展示】 【官方文档】 微信小程序插件-地图选点插件 【完善流程】 当前操作和官方文档操作有部…

Attacking Fake News Detectors via Manipulating News Social Engagement(2023 WWW)

Attacking Fake News Detectors via Manipulating News Social Engagement----《通过操纵新闻社交互动来攻击假新闻检测器》 摘要 在年轻一代中&#xff0c;获取新闻的主要来源之一是社交媒体。随着新闻在各种社交媒体平台上日益流行&#xff0c;虚假信息和毫无根据的言论的传…

【端到端可微2】链式法则,论文:Introduction to Gradient Descent and Backpropagation Algorithm

论文&#xff1a;Introduction to Gradient Descent and Backpropagation Algorithm 文章目录 0 前言1 链式法则定义作用 2 单神经元的正向传播forward propagation定义z 激活函数 3 损失函数定义 4 损失函数对权重张量的偏导数定义z对w求偏导l对z求偏导 5 多个神经元的正向传播…

企业软件的分类|app小程序网站定制开发

企业软件的分类|app小程序网站定制开发 企业软件是指为满足企业管理和运营需求而设计和开发的一类软件&#xff0c;它通常用于支持企业的各项业务活动和流程。根据其功能和应用领域的不同&#xff0c;可以将企业软件分为以下几类。 1. 企业资源计划&#xff08;ERP&#xff09…

Android性能优化 - 从SharedPreferences到DataStore

前言 对于android开发者们来说&#xff0c;SharedPreferences已经是一个老生常谈的话题了&#xff0c;之所以还在性能优化这个专栏中再次提到&#xff0c;是因为在实际项目中还是会有很多使用到的地方&#xff0c;同时它也有足够的“坑”&#xff0c;比如常见的主进程阻塞&…

k8s中批量处理Pod应用的Job和CronJob控制器介绍

目录 一.Job控制器 1.简介 2.Jobs较完整解释 3.示例演示 4.注意&#xff1a;如上例的话&#xff0c;执行“kubectl delete -f myJob.yaml”就可以将job删掉 二.CronJob&#xff08;简写为cj&#xff09; 1.简介 2.CronJob较完整解释 3.案例演示 4.如上例的话&#xf…

Tomcat的安装及其使用

一.下载安装 本文下载的是8.5版本的&#xff0c;下载链接&#xff1a;Apache Tomcat - Welcome! 切记解压缩的目录不要有中文存在。 二.启动Tomcat 在解压缩之后&#xff0c;会有很多文件存在&#xff0c;但是我们只需要在意两个文件&#xff01; webapps 目录 . web applica…

亚马逊产品如何在 TikTok 上推广?

对亚马逊卖家而言&#xff0c;TikTok是提升品牌社交媒体影响力的理想平台。该平台在过去一年中实现了飞速增长&#xff0c;使得营销变得既快捷又有趣&#xff0c;且高效。本文将详细阐述如何在TikTok推广亚马逊产品&#xff0c;并如何策划更强大的品牌营销活动。 各大品牌纷纷…

Anemone库的爬虫程序代码示例

以下是代码&#xff1a; ruby require anemone # 设置代理服务器 Anemone.proxies { http > "", https > "" } # 定义爬取的URL url # 使用Anemone进行爬取 Anemone.crawl(url) do |page| # 使用正则表达式找出所有的视频链接 video_…

Chrome显示分享按钮

分享按钮不见了&#xff01; Chrome://flags Chrome Refresh 2023 Disabled 左上角的标签搜索会到右上角。

Git - cherry-pick

文章目录 前言git资源 前言 本地 Git 仓库有两个分支&#xff0c;分别为 main 和 dev&#xff0c;dev 是 main 在 hash 为 a2 的时候创建的开发分支&#xff1a; 现在需要将 dev 分支中 hash 为 b1 的 commit 单独合并到分支 main 去&#xff1a; 这种将 dev 中部分特定 commi…

Windows系统如何远程控制Realme手机?

realme使用的是realme UI系统。realme UI是realme研发的操作系统&#xff1b;realme UI 1.0基于安卓10系统&#xff0c;realme UI 2.0基于安卓11系统&#xff0c;realme UI 3.0基于安卓12系统。 对于安卓4.0及以上系统的手机&#xff0c;都可以通过软件AirDroid实现远程控制。 …

JavaScript黑科技:简洁有用的一行代码,让你的开发效率飙升!

说在前面 在这篇技术博客中&#xff0c;我们将向你介绍一些令人惊叹的JavaScript黑科技&#xff0c;这些只需一行代码就能实现的简洁而有用的功能&#xff0c;将极大地提升你的开发效率。无论是优化代码、增加交互性&#xff0c;还是实现复杂的逻辑&#xff0c;这些代码片段将成…

echarts图表显示不全

图表显示是显示了&#xff0c;但是没有展示全部&#xff0c;一看控制台div的高度只有1px了&#xff0c;手动修改高度也只是拉伸图表&#xff0c;并没有按规定的尺寸展示 随之开始思考为什么呢 ? ? ? 因为 Echarts 的依赖是惰性的&#xff0c;需要手动设置resize&#xff0…

Android textView 显示: STRING_TOO_LARGE

默认情况下&#xff0c;TextView只能显示大约32K的字符。如果你的字符串超过这个限制&#xff0c;你将收到一个错误&#xff1a;“String too large”。 <string content" ...."/>问题点是&#xff1a;getResource().getString(R.string.content) 得到的是&am…

TableAgent:首个国产可私有部署的企业级Code Interpreter

TableAgent公测地址&#xff1a;https://tableagent.DataCanvas.com 数字化时代&#xff0c;数据分析的重要性犹如空气般无处不在。商业数据分析是数字化管理、智能决策的基础&#xff0c;同时数据分析又是一个专业性极强的工作&#xff0c;描述性分析、诊断性分析、预测性分…

【Azure 架构师学习笔记】- Azure Databricks (1) - 环境搭建

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Databricks】系列。 前言 Databricks 已经成为了数据科学的必备工具&#xff0c;今时今日你已经很难抛开它来谈大数据&#xff0c;它常用于做复杂的ETL中的T&#xff0c; 数据分析&#xff0c;数据挖掘等&#xff0c;…

论文学习-Attention Is All You Need

Attention Is All You Need 目前暂时不会用到&#xff0c;大概了解一下即可。 Recurrent model 序列化的计算方式&#xff0c;难以并行&#xff0c;随着序列的增长&#xff0c;以前的记忆会逐渐丢失。而Attention机制可以观察到句子中所有的信息&#xff0c;不受距离影响&…

MySQL中的JOIN与IN:性能对比与最佳实践

文章目录 JOIN与IN的基本介绍JOININ JOIN与IN性能对比使用JOIN的查询使用IN的查询 何时使用JOIN何时使用IN性能优化的其他考虑因素总结 &#x1f389;MySQL中的JOIN与IN&#xff1a;性能对比与最佳实践 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT陈…

基于单片机设计的激光测距仪(采用XKC-Kl200模块)

一、前言 随着科技的不断进步和应用需求的增加&#xff0c;测距仪成为了许多领域必备的工具之一。传统的测距仪价格昂贵、体积庞大&#xff0c;使用起来不够方便。本项目采用STC89C52单片机作为主控芯片&#xff0c;结合XKC-KL200激光测距模块和LCD1602显示器&#xff0c;实现…