耀极客论坛

 找回密码
 立即注册
查看: 633|回复: 0

利用vue3+threejs仿iView官网大波浪特效实例

[复制链接]

336

主题

318

帖子

22万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
220555
发表于 2022-5-9 00:30:11 | 显示全部楼层 |阅读模式
  最近好几个vue项目都是用ivew作为UI框架,所以下面这篇文章主要给大家介绍了关于如何利用vue3 + threejs仿iView官网大波浪特效的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

前言
  Threejs可以理解为是一个web端三维引擎(渲染模型,数据可视化),如果有接触过UnralEngine 4(虚幻四)等游戏引擎的,应该很容易理解在一个三维场景必备的每一个部件(场景,渲染器,网格模型,材质,光源,色相机)。好的,基础知识咱们先跳过,直接上实现的过程

一、效果图
  先上最终效果图:

  具体效果可参考iview官方界面iView - 一套高质量的UI组件库
  大波浪效果,使用的是three.js的官方例子,需要先安装three.js支持,具体可以看官方实例 three.js examples (threejs.org)

二、代码
  1.安装threejs
  1. npm install --save three
复制代码
  2.代码(复制可用) components文件夹新建组件waves.vue,直接复制代码如下,可直接运行:
  1. ‹template>
  2.   ‹div id="iviewBg">‹/div>
  3. ‹/template>
  4. ‹script>
  5. import * as THREE from "three";
  6. 显示右上角fps框
  7. // import Stats from "./stats.module";
  8. import { onMounted } from "vue";
  9. export default {
  10.   props: {
  11.   //控制x轴波浪的长度
  12.     amountX: {
  13.       type: Number,
  14.       default: 50,
  15.     },
  16.     //控制y轴波浪的长度
  17.     amountY: {
  18.       type: Number,
  19.       default: 50,
  20.     },
  21.     //控制点颜色
  22.     color: {
  23.       type: String,
  24.       default: "#097bdb",
  25.     },
  26.     //控制波浪的位置
  27.     top: {
  28.       type: Number,
  29.       default: 350,
  30.     },
  31.   },
  32.   setup(props) {
  33.     const SEPARATION = 100;
  34.     // let stats;
  35.     let container, camera, scene, renderer;
  36.     let particles,
  37.       count = 0;
  38.     let mouseX = 0;
  39.     let windowHalfX = window.innerWidth / 2;
  40.     function init() {
  41.       container = document.createElement("div");
  42.       document.getElementById("iviewBg").appendChild(container);
  43.       //创建透视相机
  44.       camera = new THREE.PerspectiveCamera(
  45.         75, //摄像机视锥体垂直视野角度
  46.         window.innerWidth / window.innerHeight, //摄像机视锥体长宽比
  47.         1, //摄像机视锥体近端面
  48.         10000 //摄像机视锥体远端面
  49.       );
  50.       //设置相机z轴视野
  51.       camera.position.z = 1000;
  52.       //创建场景
  53.       scene = new THREE.Scene();
  54.       const numParticles = props.amountX * props.amountY;
  55.       const positions = new Float32Array(numParticles * 3);
  56.       const scales = new Float32Array(numParticles);
  57.       let i = 0,
  58.         j = 0;
  59.       // 初始化粒子位置和大小
  60.       for (let ix = 0; ix ‹ props.amountX; ix++) {
  61.         for (let iy = 0; iy ‹ props.amountY; iy++) {
  62.           positions[i] = ix * SEPARATION - (props.amountX * SEPARATION) / 2; // x
  63.           positions[i + 1] = 0; // y
  64.           positions[i + 2] = iy * SEPARATION - (props.amountY * SEPARATION) / 2; // z
  65.           scales[j] = 1;
  66.           i += 3;
  67.           j++;
  68.         }
  69.       }
  70.       //是面片、线或点几何体的有效表述。包括顶点位置,面片索引、法相量、颜色值、UV 坐标和自定义缓存属性值。使用 BufferGeometry 可以有效减少向 GPU 传输上述数据所需的开销
  71.       const geometry = new THREE.BufferGeometry();
  72.       geometry.setAttribute(
  73.         "position",
  74.         new THREE.BufferAttribute(positions, 3)
  75.       );
  76.       geometry.setAttribute("scale", new THREE.BufferAttribute(scales, 1));
  77.       //着色器材质(ShaderMaterial),设置球的大小,颜色,等
  78.       const material = new THREE.ShaderMaterial({
  79.         uniforms: {
  80.           //设置球的颜色
  81.           color: { value: new THREE.Color(props.color) },
  82.         },
  83.         //控制球的大小
  84.         vertexShader:
  85.           "attribute float scale; void main() {vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );gl_PointSize = scale * ( 300.0 / - mvPosition.z );gl_Position = projectionMatrix * mvPosition;}",
  86.         fragmentShader:
  87.           "uniform vec3 color;void main() {if ( length( gl_PointCoord - vec2( 0.5, 0.5 ) ) > 0.475 ) discard;gl_FragColor = vec4( color, 1.0 );}",
  88.       });
  89.       //一个用于显示点的类。
  90.       particles = new THREE.Points(geometry, material);
  91.       //往场景中添加点
  92.       scene.add(particles);
  93.       //alpha - canvas是否包含alpha (透明度)。默认为 false。
  94.       //渲染器的背景色默认为黑色,设置渲染器的背景色为透明
  95.       renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
  96.       renderer.setPixelRatio(window.devicePixelRatio);
  97.       renderer.setClearAlpha(0);
  98.       renderer.setSize(window.innerWidth, window.innerHeight);
  99.       container.appendChild(renderer.domElement);
  100.       //显示右上角fps框
  101.       // stats = new Stats();
  102.       //   container.appendChild(stats.dom);
  103.       container.style.touchAction = "none";
  104.       //监听鼠标移动事件
  105.       container.addEventListener("pointermove", onPointerMove);
  106.       //调整波浪的位置
  107.       container.style.position = "relative";
  108.       container.style.top = `${props.top}px`;
  109.       window.addEventListener("resize", onWindowResize);
  110.     }
  111.     function render() {
  112.       camera.position.x += (mouseX - camera.position.x) * 0.05;
  113.       camera.position.y = 400;
  114.       camera.lookAt(scene.position);
  115.       const positions = particles.geometry.attributes.position.array;
  116.       const scales = particles.geometry.attributes.scale.array;
  117.       // 设置粒子位置和大小
  118.       let i = 0,
  119.         j = 0;
  120.       for (let ix = 0; ix ‹ props.amountX; ix++) {
  121.         for (let iy = 0; iy ‹ props.amountY; iy++) {
  122.           positions[i + 1] =
  123.             Math.sin((ix + count) * 0.3) * 50 +
  124.             Math.sin((iy + count) * 0.5) * 50;
  125.           scales[j] =
  126.             (Math.sin((ix + count) * 0.3) + 1) * 10 +
  127.             (Math.sin((iy + count) * 0.5) + 1) * 10;
  128.           i += 3;
  129.           j++;
  130.         }
  131.       }
  132.       particles.geometry.attributes.position.needsUpdate = true;
  133.       particles.geometry.attributes.scale.needsUpdate = true;
  134.       renderer.render(scene, camera);
  135.       count += 0.1;
  136.     }
  137.     function onWindowResize() {
  138.       windowHalfX = window.innerWidth / 2;
  139.       camera.aspect = window.innerWidth / window.innerHeight;
  140.       camera.updateProjectionMatrix();
  141.       renderer.setSize(window.innerWidth, window.innerHeight);
  142.     }
  143.     //监听鼠标移动事件
  144.     function onPointerMove(event) {
  145.       console.log(event);
  146.       if (event.isPrimary === false) return;
  147.       mouseX = event.clientX - windowHalfX;
  148.     }
  149.     function animate() {
  150.       requestAnimationFrame(animate);
  151.       render();
  152.       //fps 实时更新
  153.       // stats.update();
  154.     }
  155.     onMounted(() => {
  156.       init();
  157.       animate();
  158.     });
  159.     return {};
  160.   },
  161. };
  162. ‹/script>
  163. ‹style lang="scss" scoped>
  164. #iviewBg {
  165.   width: 100%;
  166.   height: 100vh;
  167.   background: url("../assets/wavesBg.png") no-repeat;
  168.   overflow: hidden;
  169. }
  170. ‹/style>
复制代码
  3.使用
  直接在login登录页面引入组件使用
  1. ‹template>
  2.   ‹wavesBg :top="250">‹/wavesBg>
  3.   
  4.   ‹div class="login-container">
  5.   ‹/div>
  6. ‹/template>
  7. ‹script>
  8. import wavesBg from "../components/wavesBg";
  9. export default {
  10.   name: "",
  11.   components: {
  12.     wavesBg,
  13.   },
  14.   setup() {
  15.    
  16.     return {
  17.      
  18.     };
  19.   },
  20. };
  21. ‹/script>
复制代码
三、背景图片素材

  如果不清晰可以去官方界面f12拿,iView - 一套高质量的UI组件库
  如下图所示


总结
  到此这篇关于利用vue3 + threejs仿iView官网大波浪特效的文章就介绍到这了,更多相关vue3+threejs仿大波浪特效内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|耀极客论坛 ( 粤ICP备2022052845号-2 )|网站地图

GMT+8, 2022-12-10 03:37 , Processed in 0.068405 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表