three.js绘制网波浪

阅读: 评论:0

three.js绘制网波浪

three.js绘制网波浪

无图不欢,先上图

使用方法(以vue3为例)

<template><div class="net" ref="net"></div>
</template><script setup>
import { ref, onMounted } from 'vue'
import NetAnimation from '@/utils/netAnimation.js'let net = ref(null)
onMounted(() => {new NetAnimation({dom: net.value,pointLightsAttr: [{},{},{}],axesHelperAttr: {show: true,length: 100},controlAttr: {show: true}})
})</script><style scoped lang="scss">
{width: 100%;height: 100%;background-color: #02112e;
}
</style>

netAnimation.js源码

import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";class NetAnimation {constructor(opt) {this.dom = opt.domthis.w = nullthis.h = nullthisMaxY = optMaxYthis.scene = derer = nullthis.camera = nullthis.cameraAttr = opt.cameraAttrthis.ambientLight = nullthis.ambientLightAttr = opt.ambientLightAttrthis.pointLights = []this.pointLightsAttr = opt.pointLightsAttrthis.axesHelper = nullthis.axesHelperAttr = l = lAttr = lAttrthis.plane = nullthis.planeAttr = opt.planeAttrthis.animationIndex = questAnimationFrame = nullthis.init()}init = () => {if(!this.dom){return}this.w = this.dom.clientWidth * (window.devicePixelRatio || 1)this.h = this.dom.clientHeight * (window.devicePixelRatio || 1)// 创建场景this.scene = ateScene()// 创建derer = ateWebGLRenderer({dom: this.dom});// 创建相机const cameraAttr = {style: {fov: 45,aspect: this.w / this.h,near: 0.01,far: 10000},position: {x: this.w / 2,y: this.w / 2,z: this.h * 2}}if(this.cameraAttr){this.cameraAttr = Object.assign(cameraAttr, this.cameraAttr)}else{this.cameraAttr = cameraAttr}this.camera = atePerspectiveCamera(this.cameraAttr.style)this.camera.position.set(this.cameraAttr.position.x, this.cameraAttr.position.y, this.cameraAttr.position.z);this.camera.lookAt(this.scene.position);// 创建环境光const ambientLightAttr = {show: true,style: {color: "#fff",intensity: 0.1}}if(this.ambientLightAttr){this.ambientLightAttr = Object.assign(ambientLightAttr, this.ambientLightAttr)}else{this.ambientLightAttr = ambientLightAttr}if(this.ambientLightAttr.show){this.ambientLight = ateAmbientLight(this.ambientLightAttr.style);this.scene.add(this.ambientLight);}// 创建点光源if(!thisMaxY){thisMaxY = 60}const pointLightAttr =  [{style: {color: '#fff',intensity: 0.8,distance: this.w},position: {x: this.w * 0.1,y: thisMaxY * 4,z: 0}},{style: {color: '#fff',intensity: 1,distance: this.w},position: {x: - this.w * 0.2,y: thisMaxY * 4,z: - thisMaxY * 4}},{style: {color: '#fff',intensity: 1,distance: this.w},position: {x: this.w,y: thisMaxY * 4,z: thisMaxY * 4}}]if(this.pointLightsAttr?.length){this.pointLightsAttr.forEach((pointLightItem, pointLightIndex) => {pointLightItem = Object.assign(pointLightAttr[pointLightIndex % pointLightAttr.length], pointLightItem)const pointLight = atePointLight(pointLightItem.style);pointLight.position.set(pointLightItem.position.x, pointLightItem.position.y, pointLightItem.position.z);this.pointLights.push(pointLight)})this.scene.add(...this.pointLights);}// 创建辅助线const axesHelperAttr = {show: false,length: 100}if(this.axesHelperAttr){this.axesHelperAttr = Object.assign(axesHelperAttr, this.axesHelperAttr)}else{this.axesHelperAttr = axesHelperAttr}if(this.axesHelperAttr.show){this.axesHelper = ateAxesHelper(this.axesHelperAttr.length)this.scene.add(this.axesHelper);}// 创建轨道控制const controlAttr = {show: false}lAttr){lAttr = Object.assign(controlAttr, lAttr)}else{lAttr = controlAttr}lAttr.show){ateControl(this.camera, this.dom);}let planeAttr = {width: this.w,height: this.h,widthSegments: Math.floor(this.w / 20),heightSegments: Math.floor(this.h / 60)}if(this.planeAttr){this.planeAttr = Object.assign(planeAttr, this.planeAttr)}else{this.planeAttr = planeAttr}const geometry = atePlaneGeometry(this.planeAttr)const material = ateMeshPlaneMaterial({color: "#ffffff",wireframe: true,});this.plane = ateMesh({geometry, materialBasic: material});ation.x = Math.PI * -0.5;// ation.z = 45 * (Math.PI / 180);// this.plane.position.z = 100;this.scene.add( this.plane )// 渲染der()}render = () => {//循环调用questAnimationFrame = der);this.animation()der(this.scene, this.camera);}unmount = () => {questAnimationFrame)}animation = () => {let animationSpeed = 10let sinXNum = this.planeAttr.widthSegmentslet sinYNum = this.planeAttr.heightSegmentsconst geometry = ryconst att_p = Attribute('position');let i = 0;let xi = 0let yi = 0while(i < unt){let x = X(i)let y = Y(i)xi = Math.floor(i / sinXNum)yi = i - xi * sinXNumlet z = (Math.sin(((xi + this.animationIndex / animationSpeed) % sinXNum / sinXNum * Math.PI * 2)) + Math.sin(((yi + xi + this.animationIndex / animationSpeed) % sinYNum / sinYNum * Math.PI * 2))) * (thisMaxY / 2)att_p.setXYZ( i, x, y, z );i += 1;}dsUpdate = true;geometryputeVertexNormals();this.animationIndex++this.animationIndex %= sinXNum * sinYNum * animationSpeed}// 以下皆为实体创建方法createScene = () => {return new THREE.Scene();}createPerspectiveCamera = ({ fov, aspect, near, far }) => {// fov — 摄像机视锥体垂直视野角度// aspect — 摄像机视锥体长宽比// near — 摄像机视锥体近端面// far — 摄像机视锥体远端面return new THREE.PerspectiveCamera(fov, aspect, near, far);}createWebGLRenderer = ({ dom, width, height }) => {// renderDom — dom// width — 渲染宽度 一般取domclientWidth// height — 渲染高度 一般取clientHeightif (width === undefined) {width = dom.clientWidth;}if (height === undefined) {height = dom.clientHeight;}const renderer = new THREE.WebGLRenderer();renderer.setPixelRatio(window.devicePixelRatio || 1);renderer.setClearColor('#fff', 0); //设置背景颜色和透明度renderer.setSize(width, height);dom.appendChild(renderer.domElement);return renderer;}createAmbientLight = ({ color, intensity }) => {// color - (可选参数)) 十六进制光照颜色。 缺省值 0xffffff (白色)。// intensity - (可选参数) 光照强度。 缺省值 1。return new THREE.AmbientLight(color, intensity);}createPointLight = ({ color, intensity, distance, decay }) => {// color - (可选参数)) 十六进制光照颜色。 缺省值 0xffffff (白色)。// intensity - (可选参数) 光照强度。 缺省值 1。// distance - 这个距离表示从光源到光照强度为0的位置。 当设置为0时,光永远不会消失(距离无穷大)。缺省值 0.// decay - 沿着光照距离的衰退量。缺省值 2。return new THREE.PointLight(color, intensity, distance, decay);}createPlaneGeometry = ({width, height, widthSegments, heightSegments}) => {return new THREE.PlaneGeometry(width, height, widthSegments, heightSegments);}createMeshPlaneMaterial = (data) => {return new THREE.MeshLambertMaterial(data);}createMesh = ({geometry, materialBasic}) => {return new THREE.Mesh(geometry, materialBasic);}createAxesHelper = (length) => {return new THREE.AxesHelper(length)}createControl = (camera, dom) => {return new OrbitControls(camera, dom);};
}export default NetAnimation

如果电脑性能不错,可以考虑使用以下netAnimation2.js源码

import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";class NetAnimation {constructor(opt) {this.dom = opt.domthis.w = nullthis.h = nullthisMaxY = optMaxYthis.scene = derer = nullthis.camera = nullthis.cameraAttr = opt.cameraAttrthis.ambientLight = nullthis.ambientLightAttr = opt.ambientLightAttrthis.pointLights = []this.pointLightsAttr = opt.pointLightsAttrthis.axesHelper = nullthis.axesHelperAttr = l = lAttr = lAttrthis.points = []this.lines = []this.isSameNormalStyle = opt.isSameNormalStylethis.pointAttr = opt.pointAttrthis.lineAttr = opt.lineAttrthis.pointsAttr = []this.linesArrt = []this.animationIndex = questAnimationFrame = nullthis.init()}init = () => {if(!this.dom){return}this.w = this.dom.clientWidth * (window.devicePixelRatio || 1)this.h = this.dom.clientHeight * (window.devicePixelRatio || 1)// 创建场景this.scene = ateScene()// 创建derer = ateWebGLRenderer({dom: this.dom});// 创建相机const cameraAttr = {style: {fov: 45,aspect: this.w / this.h,near: 0.01,far: 10000},position: {x: this.w / 2,y: this.w / 2,z: this.h * 2}}if(this.cameraAttr){this.cameraAttr = Object.assign(cameraAttr, this.cameraAttr)}else{this.cameraAttr = cameraAttr}this.camera = atePerspectiveCamera(this.cameraAttr.style)this.camera.position.set(this.cameraAttr.position.x, this.cameraAttr.position.y, this.cameraAttr.position.z);this.camera.lookAt(this.scene.position);// 创建环境光const ambientLightAttr = {show: true,style: {color: "#fff",intensity: 0.1}}if(this.ambientLightAttr){this.ambientLightAttr = Object.assign(ambientLightAttr, this.ambientLightAttr)}else{this.ambientLightAttr = ambientLightAttr}if(this.ambientLightAttr.show){this.ambientLight = ateAmbientLight(this.ambientLightAttr.style);// this.scene.add(this.ambientLight);}// 创建点光源if(!thisMaxY){thisMaxY = 100}const pointLightAttr =  [{style: {color: '#fff',intensity: 0.8,distance: this.w},position: {x: this.w * 0.1,y: thisMaxY * 4,z: 0}},{style: {color: '#fff',intensity: 1,distance: this.w},position: {x: - this.w * 0.2,y: thisMaxY * 4,z: - thisMaxY * 4}},{style: {color: '#fff',intensity: 1,distance: this.w},position: {x: this.w,y: thisMaxY * 4,z: thisMaxY * 4}}]if(this.pointLightsAttr?.length){this.pointLightsAttr.forEach((pointLightItem, pointLightIndex) => {pointLightItem = Object.assign(pointLightAttr[pointLightIndex % pointLightAttr.length], pointLightItem)const pointLight = atePointLight(pointLightItem.style);pointLight.position.set(pointLightItem.position.x, pointLightItem.position.y, pointLightItem.position.z);this.pointLights.push(pointLight)})this.scene.add(...this.pointLights);}// 创建辅助线const axesHelperAttr = {show: false,length: 100}if(this.axesHelperAttr){this.axesHelperAttr = Object.assign(axesHelperAttr, this.axesHelperAttr)}else{this.axesHelperAttr = axesHelperAttr}if(this.axesHelperAttr.show){this.axesHelper = ateAxesHelper(this.axesHelperAttr.length)this.scene.add(this.axesHelper);}// 创建轨道控制const controlAttr = {show: false}lAttr){lAttr = Object.assign(controlAttr, lAttr)}else{lAttr = controlAttr}lAttr.show){ateControl(this.camera, this.dom);}// 创建点、线console.time('a')this.initPointLineData()if(this.pointsAttr?.length){// 点geometry、material// let pointGeometry = null// let pointMaterial = null// let pointmMesh = null// 线geometry、materiallet lineMaterial = nullif(this.isSameNormalStyle === undefined){this.isSameNormalStyle = true// pointGeometry = ateSphereGeometry(this.al.geometry);// pointMaterial = ateMeshLambertMaterial(this.al.material);// pointmMesh = ateMesh({geometry: pointGeometry, materialBasic: pointMaterial});lineMaterial = ateMeshLineMaterial(this.al.material);}// this.pointsAttr.forEach(pointAttrItem => {//     // 创建点Mesh//     let mesh = null//     if(!this.isSameNormalStyle){//         pointGeometry = ateSphereGeometry(al.geometry);//         pointMaterial = ateMeshLambertMaterial(al.material);//         mesh = ateMesh({geometry: pointGeometry, materialBasic: pointMaterial});//     }else{//         mesh = pointmMesh.clone();//     }//     mesh.position.set(pointAttrItem.position.x, pointAttrItem.position.y, pointAttrItem.position.z);//     this.points.push(mesh)// })this.linesArrt.forEach(lineAttrItem => {// 创建线Meshlet linePositions = []lineAttrItem.forEach(linePoint => {let i = (w * l) + llinePositions.push({...this.pointsAttr[i].position})})const lineGeometry = ateLineGeometry(linePositions);// if(!this.isSameNormalStyle){//     lineMaterial = ateMeshLineMaterial(al.material);// }const lineMesh = ateMesh({geometry: lineGeometry, materialBasic: lineMaterial});this.lines.push(lineMesh)})// this.scene.add(...this.points);this.scene.add(...this.lines);}console.timeEnd('a')// 渲染der()}initPointLineData() {const pointAttr = {width: this.w,height: Math.floor(this.w / 2),row: Math.floor(this.w / 40),col: Math.floor(this.w / 20),// width: this.w * 2,// height: this.w,// row: this.w / 20,// col: this.w / 10,// row: 10,// col: 10,style: {normal: {geometry: {radius: 3,widthSegments: 320,heightSegments: 160,},material: {color: "#ffffff",wireframe: false, //是否将几何体渲染为线框,默认值为false(即渲染为平面多边形)},},light: {geometry: {radius: 1,widthSegments: 320,heightSegments: 160,},material: {color: "#ffffff",wireframe: false,},}}}if(this.pointAttr){this.pointAttr = Object.assign(pointAttr, this.pointAttr)}else{this.pointAttr = pointAttr}const lineAttr = {style: {normal: {material: {color: "#fff",// color: "#3587C7",linewidth: 1,},},light: {material: {color: "#ffffff",linewidth: 1,},}}};if(this.lineAttr){this.lineAttr = Object.assign(lineAttr, this.lineAttr)}else{this.lineAttr = lineAttr}const startX = -this.pointAttr.width / 2const startZ = -this.pointAttr.height / 2const stepX = this.pointAttr.width / lconst stepZ = this.pointAttr.height / wconst sinXNum = w / 4const sinZNum = l / 4for(let i = 0 ; i < w; i++){for(let j = 0 ; j < l; j++){const x = startX + j * stepXconst z = startZ + i * stepZconst y = (Math.sin((i % sinXNum / sinXNum * Math.PI * 2)) + Math.sin(((j + i) % sinZNum / sinZNum * Math.PI * 2))) * (thisMaxY / 2)this.pointsAttr.push({row: i,col: j,position: {x, y, z},style: {...this.pointAttr.style}})if(!this.linesArrt[i]){this.linesArrt[i] = []}this.linesArrt[i][j] = {row: i,col: j}if(!this.linesArrt[w + j]){this.linesArrt[w + j] = []}this.linesArrt[w + j][i] = {row: i,col: j}}}}render = () => {//循环调用questAnimationFrame = der);this.animation()der(this.scene, this.camera);}unmount = () => {questAnimationFrame)}animation = () => {const sinXNum = w / 4const sinZNum = l / 4const count = w * lconst animationSpeed = 10 //值越大越慢console.time('b')// if(this.animationIndex % 10 === 0){this.pointsAttr.forEach((pointAttrItem, pointAttrIndex) => {const i = wconst j = lpointAttrItem.position.y = (Math.sin(((i + this.animationIndex / animationSpeed) % sinXNum / sinXNum * Math.PI * 2)) + Math.sin(((j + i + this.animationIndex / animationSpeed) % sinZNum / sinZNum * Math.PI * 2))) * 30})this.linesArrt.forEach((lineAttrItem, lineAttrIndex) => {let linePositions = []lineAttrItem.forEach(linePoint => {let i = (w * l) + llet point = this.pointsAttr[i]linePositions.push({...point.position})})const lineGeometry = ateLineGeometry(linePositions);this.updateGeometry(this.lines[lineAttrIndex].geometry, lineGeometry)})// }console.timeEnd('b')this.animationIndex++this.animationIndex %= count * animationSpeed}updateGeometry = (geometry, geometry_source) => {const att_p = Attribute('position');const att_ps = Attribute('position');let i = 0;while(i < unt){att_p.setXYZ( i, X(i), Y(i),Z(i) );i += 1;}dsUpdate = true;geometryputeVertexNormals();};rand = (n,m) => {var c = m - n + 1;return Math.floor(Math.random() * c + n);}    // 以下皆为实体创建方法createScene = () => {return new THREE.Scene();}createPerspectiveCamera = ({ fov, aspect, near, far }) => {// fov — 摄像机视锥体垂直视野角度// aspect — 摄像机视锥体长宽比// near — 摄像机视锥体近端面// far — 摄像机视锥体远端面return new THREE.PerspectiveCamera(fov, aspect, near, far);}createWebGLRenderer = ({ dom, width, height }) => {// renderDom — dom// width — 渲染宽度 一般取domclientWidth// height — 渲染高度 一般取clientHeightif (width === undefined) {width = dom.clientWidth;}if (height === undefined) {height = dom.clientHeight;}const renderer = new THREE.WebGLRenderer();renderer.setPixelRatio(window.devicePixelRatio || 1);renderer.setClearColor('#fff', 0); //设置背景颜色和透明度renderer.setSize(width, height);dom.appendChild(renderer.domElement);return renderer;}createAmbientLight = ({ color, intensity }) => {// color - (可选参数)) 十六进制光照颜色。 缺省值 0xffffff (白色)。// intensity - (可选参数) 光照强度。 缺省值 1。return new THREE.AmbientLight(color, intensity);}createPointLight = ({ color, intensity, distance, decay }) => {// color - (可选参数)) 十六进制光照颜色。 缺省值 0xffffff (白色)。// intensity - (可选参数) 光照强度。 缺省值 1。// distance - 这个距离表示从光源到光照强度为0的位置。 当设置为0时,光永远不会消失(距离无穷大)。缺省值 0.// decay - 沿着光照距离的衰退量。缺省值 2。return new THREE.PointLight(color, intensity, distance, decay);}createSphereGeometry = ({radius,widthSegments,heightSegments,phiStart,phiLength,thetaStart,thetaLength}) => {/*radius — 球体半径,默认为1。widthSegments — 水平分段数(沿着经线分段),最小值为3,默认值为32。heightSegments — 垂直分段数(沿着纬线分段),最小值为2,默认值为16。phiStart — 指定水平(经线)起始角度,默认值为0。。phiLength — 指定水平(经线)扫描角度的大小,默认值为 Math.PI * 2。thetaStart — 指定垂直(纬线)起始角度,默认值为0。thetaLength — 指定垂直(纬线)扫描角度大小,默认值为 Math.PI。*/return new THREE.SphereGeometry(radius,widthSegments,heightSegments,phiStart,phiLength,thetaStart,thetaLength);}createMeshLambertMaterial = (data) => {return new THREE.MeshLambertMaterial(data);}createLineGeometry = (points) => {// const pointsVector3 = [];// for (let i = 0; i < points.length; i++) {//     pointsVector3.push(new THREE.Vector3(points[i].x, points[i].y, points[i].z));// }// const geometry = new THREE.BufferGeometry().setFromPoints(pointsVector3);// const line = new MeshLine();// line.setGeometry(geometry);// return linelet pointsVector3 = []points.forEach(point => {pointsVector3.push(new THREE.Vector3(point.x, point.y, point.z))})let curve = new THREE.CatmullRomCurve3(pointsVector3);var CurvePath = new THREE.CurvePath();// 创建CurvePath对象// CurvePath.curves.push(line1, curve, line2);// 插入多段线条CurvePath.curves.push(curve);return new THREE.TubeGeometry(CurvePath, points.length * 10, 1, 25, false);}createMeshLineMaterial = (data) => {// return new MeshLineMaterial({//     lineWidth: data.linewidth,//     color: lor || "white",//     dashArray: data.dashArray || 0,//     transparent: true,// })return new THREE.MeshLambertMaterial({color: lor || "white"});}createMesh = ({geometry, materialBasic}) => {return new THREE.Mesh(geometry, materialBasic);}createAxesHelper = (length) => {return new THREE.AxesHelper(length)}createControl = (camera, dom) => {return new OrbitControls(camera, dom);};
}export default NetAnimation

本文发布于:2024-01-31 18:40:49,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170669764930561.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:Linux笔记
标签:波浪   js
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23