嗨,我是小路。今天主要和大家分享的主题是“vue+threeJs 生成云状特效屏幕”。
动态云状特效示例图
二、实例代码
<!--创建一个动态数字屏幕-->
<template><div class="pageBox"><div class="leftBox" ref="leftRef"></div></div></template>
<script setup>
import { onMounted, onUnmounted, reactive, ref } from 'vue';
import * as THREE from 'three';
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { getRandomColor, createLight } from '../utils/commonThree';
const leftRef = ref();
// 定义相机输出画布的尺寸(单位:像素px)
let width = window.innerWidth; //宽度
let height = window.innerHeight; //高度
// 创建3D场景对象Scene
const scene = new THREE.Scene();
//设置背景色
scene.background = new THREE.Color(0x646d59);const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
//三角形缩放过大时,会形成多种三角形形成的背景图
camera.position.z = 30;// 创建渲染器对象
const renderer = new THREE.WebGLRenderer();let tubes = [];
let material;
const createTube = () => {const geometry = new THREE.PlaneGeometry(100,100,100);material = new THREE.ShaderMaterial({transparent: true,uniforms: {time: { value: 0 },iTime:{value:0},},vertexShader: `varying vec2 vUv;void main() {vUv = uv;gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);}`,fragmentShader: `#define PI2 6.28318530718#define PI 3.1416uniform float iTime;uniform vec2 iResolution;varying vec2 vUv;float vorocloud(vec2 p){float f = 0.1;//输入坐标 p 进行周期性处理vec2 pp = cos(vec2(p.x * 14.0, (16.0 * p.y + cos(floor(p.x * 30.0)) + iTime * PI2)));//坐标 p 进行非线性扭曲p = cos(p * 12.1 + pp * 10.0 + 0.5 * cos(pp.x * 10.0));vec2 pts[4];pts[0] = vec2(0.5, 0.6);pts[1] = vec2(-0.4, 0.4);pts[2] = vec2(0.2, -0.7);pts[3] = vec2(-0.3, -0.4);float d = 1.0;for(int i = 0; i < 4; i++){pts[i].x += 0.03 * cos(float(i)) + p.x;pts[i].y += 0.03 * sin(float(i)) + p.y;d = min(d, distance(pts[i], pp));}f = 3.0 * pow(1.0 - 0.3 * d, 13.0);f = min(f, 1.0);return f;}void main() {vec2 UV = vUv;vec2 p = UV - vec2(0.1);vec4 col = vec4(0.0);col.g += 0.01;float v = vorocloud(p);//亮度v = 0.2 * floor(v * 5.0);// rgba 中的red green blue col.r += 0.3 * v;col.g += 0.6 * v;col.b += 0.5 * pow(v, 5.0);//生成屏幕的数字层数v = vorocloud(p * 1.0);//数字的亮度v = 0.1 * floor(v * 5.0);col.r += 0.3 * v;col.g += 0.2 * v;col.b += 0.1 * pow(v, 5.0);//透明度col.a = 1.0;gl_FragColor = col;}`,side: THREE.DoubleSide});const tube = new THREE.Mesh(geometry, material);return tube;
}onMounted(() => {initData()renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)//将innerHTML置空,避免append重复添加渲染leftRef.value.innerHTML = ''leftRef.value.append(renderer.domElement);})
const initData = () => {createLight(scene);for (let i = 1; i >= 0; i--) {const outSphere = createTube();tubes.push(outSphere);scene.add(outSphere);}render();
}
function render() {requestAnimationFrame(render);material.uniforms.iTime.value += 0.01;renderer.render(scene, camera);
}
onUnmounted(() => {//释放内存renderer.dispose();
})</script>
<style scoped lang="less">
.pageBox {width: 100%;height: 100vh;padding: 0;margin: 0;position: fixed;top: 0;left: 0;display: flex;justify-content: space-between;align-items: center;.rightBox {width: 100%;height: 100%;}
}
</style>
三、总结
1、想生成动态变化,需要使用iTime。
2、设置背景屏幕,不需要设置相机控制器
3、gl_FragColor是像素的颜色。如何对屏幕颜色进行调整,可以参考代码中的注释。
成长是一个持续的过程,需要一步一个脚印!
都看到这里了,记得【点赞】+【关注】哟。
参考文章:
Three.js 实现云状特效
vue+threeJs 在开发中将部分常用的代码模块封装-CSDN博客