当前位置: 首页 > article >正文

vue+ThreeJs 创建过渡圆圈效果

        嗨,我是小路。今天主要和大家分享的主题是“vue+ThreeJs 创建过渡圆圈效果”。        

今天在做着色器过渡效果练习,发现出现了很多新的函数,这些都超出了js之外,需要更多的掌握和学习。以下是自己的复盘和梳理。

1.获取距离

定义:distance获取两个点之间的距离

2.平滑过渡

定义:smoothstep函数是用来平滑插值的函数。在HLSL或者其他着色语言中,smoothstep可能用于生成平滑的过渡效果,比如在边缘模糊或者渐变时使用。

3.计算模型长度

定义length 函数用于计算向量的欧几里得长度(模长)。

二、实例代码

<!--创建一个球体-->
<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 = 5;// 创建渲染器对象
const renderer = new THREE.WebGLRenderer();let tubes = [];
let material
const createTube = () => {const geometry = new THREE.PlaneGeometry(10,10);material = new THREE.ShaderMaterial({transparent: true,uniforms: {iResolution: { value: new THREE.Vector2() },iTime: { value: 0 },},vertexShader: `varying vec2 vUv;void main() {vUv = uv;gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);}`,fragmentShader: `uniform vec2 iResolution;uniform float iTime;varying vec2 vUv;float circle(float radius, vec2 center, vec2 uv) {float d = distance(center, uv);return 1.0 - smoothstep(radius-1./iResolution.y, radius+1./iResolution.y, d);}vec2 angleRadius(vec2 uv) {float anglePixel = atan(uv.y, uv.x);//length 计算模型长度float lengthPixel = length(uv);//画一条贝塞尔曲线return vec2(anglePixel, lengthPixel);}float filterPositive(float n) {return smoothstep(0.0, 0.005, n);}void main() {// 坐标系转换vec2 uv = (vUv - 0.5) * vec2(iResolution.x/iResolution.y, 1.0)*2.0;//生成原型的半径float radius = 0.3;//边缘的宽度float ringThick = 0.05;//画一条贝塞尔曲线vec2 stPolar = angleRadius(uv);float sPolar = stPolar.x * 3.0 + iTime * 10.0;float cosSPolarTemp = cos(sPolar);float cosSPolar = filterPositive(cosSPolarTemp);vec3 color = vec3(cosSPolar);float inCircleAA = smoothstep(radius, radius + 0.005, stPolar.y);float smallCircleAA = smoothstep(radius - ringThick, radius - ringThick + 0.005, stPolar.y);vec3 col = 1.0 - vec3(inCircleAA);vec3 col_2 = 1.0 - vec3(smallCircleAA);vec3 colorGap = col - col_2;vec3 finalColor = color * colorGap;vec3 colorMask = vec3(10.0, 1.5, 1.0);finalColor /= 10.0;finalColor *= colorMask;//实现平滑过渡效果float centerCircleAA = smoothstep(0.1, 0.1 + 0.005, stPolar.y);vec3 centerCircleColor = 1.0 - vec3(centerCircleAA);centerCircleColor /= 10.0;centerCircleColor *= colorMask;vec2 centerC = vec2(0.0);float bubbleRadius = abs(sin(iTime * 3.0)) / 3.0;float bubbleCircleColor = circle(bubbleRadius, centerC, uv);//创建一个四位结构体 x、y、z、w 或者颜色 rgbavec4 bubbleColor = vec4(vec3(bubbleCircleColor) / 10.0 * colorMask, 1.0);gl_FragColor = vec4(finalColor + centerCircleColor, 1.0);gl_FragColor += bubbleColor;}`,side: THREE.DoubleSide});const tube = new THREE.Mesh(geometry, material);//设置网格的随机位置// sphere.position.set(//   (Math.random() - 0.5) * 2000,//   (Math.random() - 0.5) * 1000,//   (Math.random() - 0.5) * 1000// );return tube;
}onMounted(() => {initData()//添加相机空间const controls = new OrbitControls(camera, renderer.domElement);// controls.enableDamping = false;controls.enableZoom = false;// 如果OrbitControls改变了相机参数,重新调用渲染器渲染三维场景controls.addEventListener('change', function () {renderer.render(scene, camera); //执行渲染操作});//监听鼠标、键盘事件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);// 旋转所有三角形// tubes.forEach(tube => {//   tube.rotation.x += 0.01;//   tube.rotation.y += 0.01;//   tube.rotation.z += 0.01;// });console.log( 'dfffff',material.uniforms.iResolution);material.uniforms.iResolution.value.set(window.innerWidth,window.innerHeight);material.uniforms.iTime.value = performance.now() / 1000;renderer.render(scene, camera);
}
onUnmounted(() => {//释放内存renderer.dispose();
})</script>
<style scoped lang="less">
.pageBox {width: 100%;height: 100vh;padding: 0;margin: 0;display: flex;justify-content: space-between;align-items: center;.rightBox {width: 100%;height: 100%;}
}
</style>

三、总结

       在学习中,重新复盘了着色器的知识点,并寻找更好掌握着色器的方法,同时了解到了glsl编程中的动态过渡、获取模型长度、计算两个元素之间距离的方法。

都看到这里了,记得【点赞】+【关注】哟。

参考文章:

Threejs实现极坐标和平滑过渡特效

http://www.lryc.cn/news/2387032.html

相关文章:

  • MySQL:12_视图
  • 2025 年开源 LLM 发展趋势细致解读
  • win11+vs2022 安装opencv 4.11.0图解教程
  • n8n 读写本地文件
  • 详解3DGS
  • DEBUG设置为False 时,django默认的后台样式等静态文件丢失的问题
  • 如何提高服务器的QPS来应对618活动的并发流量
  • LlamaFirewall:开源框架助力检测与缓解AI核心安全风险
  • java基础知识回顾3(可用于Java基础速通)考前,面试前均可用!
  • 嵌入式软件架构规范之 - 分层设计
  • 电脑无法识别打印机usb设备怎么办 一键解决!
  • Elasticsearch Synthetic _source
  • C++ -- vector
  • GitLab-CI简介
  • 深入研究Azure 容器网络接口 (CNI) overlay
  • Python打卡第37天
  • 使用 OpenCV 构建稳定的多面镜片墙效果(镜面反射 + Delaunay 分块)
  • HTTP协议版本的发展(HTTP/0.9、1.0、1.1、2、3)
  • 零基础设计模式——结构型模式 - 桥接模式
  • C++对象的内存模型
  • SpringBoot3集成Oauth2.1——4集成Swagger/OpenAPI3
  • 基于深度学习的情绪识别检测系统【完整版】
  • 本地依赖库的版本和库依赖的版本不一致如何解决?
  • Redis学习打卡-Day7-高可用(下)
  • Spark on Yarn 高可用模式部署流程
  • AI时代新词-大模型(Large Language Model)
  • 3d tiles高级样式设计与条件渲染
  • Linux中logger命令的使用方法详解
  • 博奥龙Nanoantibody系列IP专用抗体
  • webpack构建速度和打包体积优化方案