Vue3 实现 Three.js粒子特效

效果

在这里插入图片描述

<template><div id="waves" />
</template><script setup>
import { ref, onMounted, onUnmounted } from "vue";
import * as THREE from "three";const amountX = ref(50);
const amountY = ref(50);
const color = ref("#e1b284");
const topOffset = ref(350);let count = 0;
let mouseX = 0;
let windowHalfX = null;
let camera = null;
let scene = null;
let particles = null;
let renderer = null;const init = () => {const SEPARATION = 100;const SCREEN_WIDTH = window.innerWidth;const SCREEN_HEIGHT = window.innerHeight;const container = document.createElement("div");windowHalfX = window.innerWidth / 2;container.style.position = "relative";container.style.top = `${topOffset.value}px`;container.style.height = `${SCREEN_HEIGHT - topOffset.value}px`;const waves = document.getElementById("waves");waves.appendChild(container);camera = new THREE.PerspectiveCamera(75,SCREEN_WIDTH / SCREEN_HEIGHT,1,10000,);camera.position.z = 1000;scene = new THREE.Scene();const numParticles = amountX.value * amountY.value;const positions = new Float32Array(numParticles * 3);const scales = new Float32Array(numParticles);let i = 0;let j = 0;for (let ix = 0; ix < amountX.value; ix++) {for (let iy = 0; iy < amountY.value; iy++) {positions[i] = ix * SEPARATION - (amountX.value * SEPARATION) / 2;positions[i + 1] = 0;positions[i + 2] = iy * SEPARATION - (amountY.value * SEPARATION) / 2;scales[j] = 1;i += 3;j++;}}const geometry = new THREE.BufferGeometry();geometry.setAttribute("position", new THREE.BufferAttribute(positions, 3));geometry.setAttribute("scale", new THREE.BufferAttribute(scales, 1));const material = new THREE.ShaderMaterial({uniforms: {color: { value: new THREE.Color(color.value) },},vertexShader: `attribute float scale;void main() {vec4 mvPosition = modelViewMatrix * vec4( position, 2.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 );}`,});particles = new THREE.Points(geometry, material);scene.add(particles);renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });renderer.setSize(container.clientWidth, container.clientHeight);renderer.setPixelRatio(window.devicePixelRatio);renderer.setClearAlpha(0);container.appendChild(renderer.domElement);window.addEventListener("resize", onWindowResize, { passive: false });document.addEventListener("mousemove", onDocumentMouseMove, {passive: false,});document.addEventListener("touchstart", onDocumentTouchStart, {passive: false,});document.addEventListener("touchmove", onDocumentTouchMove, {passive: false,});
};const render = () => {camera.position.x += (mouseX - camera.position.x) * 0.05;camera.position.y = 400;camera.lookAt(scene.position);const positions = particles.geometry.attributes.position.array;const scales = particles.geometry.attributes.scale.array;let i = 0;let j = 0;for (let ix = 0; ix < amountX.value; ix++) {for (let iy = 0; iy < amountY.value; 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) * 8 +(Math.sin((iy + count) * 0.5) + 1) * 8;i += 3;j++;}}particles.geometry.attributes.position.needsUpdate = true;particles.geometry.attributes.scale.needsUpdate = true;renderer.render(scene, camera);count += 0.1;
};const animate = () => {requestAnimationFrame(animate);render();
};const onDocumentMouseMove = (event) => {mouseX = event.clientX - windowHalfX;
};const onDocumentTouchStart = (event) => {if (event.touches.length === 1) {mouseX = event.touches[0].pageX - windowHalfX;}
};const onDocumentTouchMove = (event) => {if (event.touches.length === 1) {event.preventDefault();mouseX = event.touches[0].pageX - windowHalfX;}
};const onWindowResize = () => {windowHalfX = window.innerWidth / 2;camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);
};onMounted(() => {init();animate();
});onUnmounted(() => {window.removeEventListener("resize", onWindowResize);document.removeEventListener("mousemove", onDocumentMouseMove);document.removeEventListener("touchstart", onDocumentTouchStart);document.removeEventListener("touchmove", onDocumentTouchMove);
});
</script>

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

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

相关文章

ArcGIS Pro教程系列: ArcGIS Pro 将 Excel 表转换为面

数据的存在形式是多样的&#xff0c;这其中有相当一部分数据是Excel表格&#xff0c;这里给大家讲解一下如何使用 ArcGIS Pro 将 Excel 表转换为面要素&#xff0c;希望能对你有所帮助。 01&#xff1a;导入数据 02 添加XY数据 在菜单栏上选择地图&#xff0c;点击添加数据…

如何打造自己的O2O平台系统:商业模式探索与实践

大家好&#xff0c;我是微三云周丽&#xff0c;今天给大家分析当下市场比较火爆的商业模式&#xff01; 小编今天跟大伙们分享什么是O2O平台系统&#xff1f; 在数字化浪潮的推动下&#xff0c;O2O&#xff08;Online to Offline&#xff09;商业模式已成为连接线上与线下、商家…

3d模型合并怎么样不丢材质?---模大狮模型网

在3D设计中&#xff0c;合并模型是常见的操作&#xff0c;它可以帮助设计师将多个单独的模型组合成一个&#xff0c;从而简化场景并提高渲染效率。然而&#xff0c;合并模型时常常会面临一个棘手的问题&#xff1a;如何确保合并后的模型不丢失原有的材质?本文将探讨如何在合并…

C# 项目:导线计算 / 坐标转换 / 曲线放样 / 水准网 / 导线网平差

文章目录 Part.I IntroductionPart.II 软件简介Chap.I 导线计算Chap.II 坐标转换Chap.III 曲线放样Chap.IV 水准网 / 导线网平差 Part.III 软件使用过程中可能遇到的问题Reference Part.I Introduction 本文将对几个基于 C# 开发的软件进行简要的介绍&#xff0c;这些软件都是…

MT3028 正反卡牌

思路&#xff1a;贪心 &#xff1b;注意开long long 贪心策略&#xff1a;为了让结果最小&#xff0c;需要减去最大的值&#xff0c;加上较小的值。 第i张卡牌正反两面的值分别为a[i]和b[i]&#xff0c;不妨设a[i]>b[i]。i和j卡牌比较suma[]b[]&#xff0c;若sum[i]>su…

最值得收藏的30个AI工具

万能聊天类 ChatGPT4.0&#xff1a;使用范围最广的 https://chat.openai.com/ NewBing&#xff1a;使用比较困难&#xff0c;要安装插件 https://www.bing.com/new 谷歌巴德&#xff1a;国内基本无缘访问使用&#xff0c;能访问的方式不能说。 http://bard.google.com 百…

解决DataGrip连接MySQL8时出现时区错误问题

解决办法&#xff1a;在url后面拼接时区参数 ?serverTimezoneAsia/Shanghai

c++实数排序

例&#xff1a;数的三次方跟 描述&#xff1a;给定一个浮点数n&#xff0c;求它的三次方根。 输入描述&#xff1a;一个浮点数 输出描述&#xff1a;问题的解 保留6位小数 #include<bits/stdc.h> using namespace std; double n,eps1e-8; bool check (double x){retu…

【InternLM实战营---第六节课笔记】

一、本期课程内容概述 本节课的主讲老师是【樊奇】。教学内容主要包括以下三个部分&#xff1a; 1.大模型智能体的背景及介绍 2. Lagent&AgentLego框架介绍 3.Lagent&AgentLego框架实战 二、学习收获 智能体出现的背景 智能体的引入旨在克服大模型在应对复杂、动态任…

齐护K210系列教程(九)_## 播放音频文件wav

播放音频文件wav 播放音频只支持带喇叭的型号&#xff1a;AIstart_掌机、AIstart_Mini AIstart可以播放SD卡中的wav音频文件&#xff0c;在编写程序前请将文件准备好存放到SD卡内。 注&#xff1a;播放wav格式音频&#xff1a;wav格式的音频频率不能超过16KHZ。 1&#xff0…

Java高级阶段面试题库(Redis数据库、MQ消息队列、kafka、SpringBoot + SpringCloud、MySQL、JVMJUC、其它)

文章目录 1. Redis数据库篇(忽略)1.1 简单介绍一下redis1.2 单线程的redis为什么读写速度快?1.3 redis为什么是单线程的?1.4 redis服务器的的内存是多大?1.5 为什么Redis的操作是原子性的&#xff0c;怎么保证原子性的&#xff1f;1.6 你还用过其他的缓存吗&#xff1f;这些…

可持续发展:制造铝制饮料罐要消耗多少资源?

铝制饮料罐是人们经常使用的日常用品&#xff0c;无论是在购物、午休还是在自动售货机前选择喝什么的时候&#xff0c;很少有人会想知道装他们喝的饮料的罐子到底是如何制成的&#xff0c;或者这些铝罐的原材料是如何进出的。 虽然有化学品和一些合金进入铝饮料罐制造过程或成为…

CSS3 max/min-content及fit-content、fill-available值的详解

c3中对width的值多了几个值&#xff1a;fill-available, max-content, min-content, 以及fit-content。 1.width:fill-available 我们在页面中扔一个没有其他样式的<div>元素&#xff0c;则&#xff0c;此时&#xff0c;该<div>元素的width表现就是fill-availabl…

短信视频提取批量工具,免COOKIE,博主视频下载抓取,爬虫

痛点&#xff1a;关于看了好多市面的软件&#xff0c;必须要先登录自己的Dy号才能 然后找到自己的COOKIE 放入软件才可以继续搜索&#xff0c;并且无法避免长时间使用 会导致无法正常显示页面的问题。 有没有一种方法 直接可以使用软件&#xff0c;不用设置的COOKIE的方法呢 …

指针学习总结

当指针本身定义的类型不同十&#xff0c;指向的一次性取值长度也不同 数组元素的指针 数组存放字符串 数组存放字符串时存放在栈区&#xff0c;sizeof(str1) 128字节 字符指针指向字符串 str2此时存放的是h的地址&#xff0c;因此sizeof(str2) 4字节或者8字节 并且文字常量…

中职人工智能教学实训案例之Al故障分析实战

一、案例背景 随着人工智能技术的飞速发展&#xff0c;越来越多的行业和领域开始广泛应用AI技术&#xff0c;以提高生产效率、优化服务质量和创造更多价值。然而&#xff0c;AI系统的复杂性也带来了故障分析和处理的挑战。为了培养中职学生具备解决AI故障的能力&#xff0c;本案…

探索C++20高级编程:新特性、技巧与性能优化

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;注册地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…

2024年区块链链游即将迎来大爆发

随着区块链技术的不断发展和成熟&#xff0c;其应用领域也在不断扩展。其中&#xff0c;区块链链游&#xff08;Blockchain Games&#xff09;作为区块链技术在游戏行业中的应用&#xff0c;备受关注。2024年&#xff0c;区块链链游行业即将迎来爆发&#xff0c;这一趋势不容忽…

正整数的性质:和与根

目录 数字和 数字和介绍 数字和简单应用 哈沙德数 最小元素各数位之和 数字根 数字根介绍 数字根简单应用 数字和 数字和介绍 简单来说&#xff0c;数字和即一个整数数字每一位数值相加求和所得的值&#xff0c;数字和可以为任意正整数&#xff0c;使用代码获取一个数值的数字和…

zabbix6.4告警配置(短信告警和邮件告警),脚本触发

目录 一、前提二、告警配置1.邮件告警脚本配置2.短信告警脚本配置3.zabbix添加报警媒介4.zabbix创建动作4.给用户添加报警媒介 一、前提 已经搭建好zabbix-server 在需要监控的mysql服务器上安装zabbix-agent2 上述安装步骤参考我的上篇文章&#xff1a;通过docker容器安装za…