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

ThreeJs绘制手串

        ThreeJs绘制手串,先分析手串的结构,一根绳子,多个珠子,因此需要封装一个绘制珠子的方法并循环调用绘制出多个珠子,再封装一个绘制绳子的方法,绘制一根圆形闭合的绳子。另外为了方便动态调整绳子,可以定义变量,包括珠子个数,绳子直径,珠子的直径。

        首先需要绘制ThreeJs的场景,之前的章节都有,就不做赘述,初始化场景,相机,灯光,渲染器等,然后开始绘制绳子,为了方便后续修改,我们把绳子的参数,包括绳子的半径,绳子上珠子的个数,颜色等作为一个变量的属性统一定义。

 resultData:{bead:[],bracelet:{braceletRadius:12,beadCount:12,braceletColor:'#000000',lineWidth:7,beadRadius:2},}, // 创建连接珠子的线const curve = new THREE.EllipseCurve(0, 0,  // 椭圆中心x,y坐标this.resultData.bracelet.braceletRadius, this.resultData.bracelet.braceletRadius,  // 椭圆长半轴和短半轴0, 2 * Math.PI  // 起始角度和结束角度,设置为0到2π使曲线闭合);const points = curve.getPoints(50);  // 获取50个点const geometry = new THREE.BufferGeometry().setFromPoints(points);const material = new THREE.LineBasicMaterial({color: this.resultData.bracelet.braceletColor,linewidth: this.resultData.bracelet.lineWidth,});const line = new THREE.Line(geometry, material);line.name='bracelet'this.scene.add(line);

然后就可以得到一根绳子

随后我们开发绘制珠子的方法,绘制珠子就是绘制一个小的球体,并按照绳子排列,为了方便后续操作,我们也把珠子的直径,珠子的颜色引用变量,方便后期修改

        let beadMaterial = new THREE.MeshPhongMaterial({color: this.beadData.beadColor,specular: this.beadData.beadColor });  //前  0xafc0ca :灰色if(this.beadData.beadMaterialName && this.beadData.beadMaterialName !== ""){let texturebracelet = new THREE.TextureLoader().load(this.beadData.beadMaterialUrl, function (texture) {texture.wrapS = texture.wrapT = THREE.RepeatWrapping;texture.repeat.set(1, 1);})beadMaterial.map = texturebracelet}const angle = (i / this.resultData.bracelet.beadCount) * 2 * Math.PI;const x = Math.cos(angle) * this.resultData.bracelet.braceletRadius;const y = Math.sin(angle) * this.resultData.bracelet.braceletRadius;const beadGeometry = new THREE.SphereGeometry(this.resultData.bracelet.beadRadius, 32, 32);const bead = new THREE.Mesh(beadGeometry, beadMaterial);bead.position.set(x, y, 0);bead.name='bead'+ithis.scene.add(bead);

此时就得到一个基础的手串了

然后,我们设置一些输入框,将刚才的参数添加到输入框中,并添加重新绘制按钮,在修改参数后重新绘制手串以按照我们设定的参数进行绘制

 <div style="position:absolute;z-index: 100;width:200px; left:30px;top:20px;"><el-form :inline="true" class="demo-form-inline"><el-form-item label="手串半径"><el-input v-model="resultData.bracelet.braceletRadius" style="width:80px;" type="number" placeholder="手串半径" /></el-form-item><el-form-item label="珠子个数" ><el-input v-model="resultData.bracelet.beadCount" style="width:80px;" type="number" placeholder="珠子个数" /></el-form-item><el-form-item label="珠子半径" ><el-input v-model="resultData.bracelet.beadRadius" style="width:80px;" type="number" placeholder="珠子半径" /></el-form-item></el-form><el-button type="primary" @click="reDraw">重新绘制</el-button></div>reDraw(){for (let i = 0; i < this.scene.children.length; i++) {if (this.scene.children[i].name.indexOf("bead") !== -1) {this.scene.remove(this.scene.children[i])i--}}this.initBracelet();},

然后可以得到这样一个效果:

但是一直是白色的柱子显得不够美观,可以再添加动态修改柱子的贴图,之前章节有学过threejs的点击事件,因此可以采用点击的方式给每个柱子着色添加贴图,首先添加一些图片并设置贴图

      materialList:[{name:'珍珠',url:'/static/images/material/zhenzhu.png'},{name:'紫水晶',url:'/static/images/material/zishuijing.png'},{name:'和田玉',url:'/static/images/material/yu.jpg'},{name:'水晶',url:'/static/images/material/shuijing.png'}],    <div style="position:absolute;;left:30%;top:0;z-index:10"><el-radio-group v-model="material" @input="selectMaterial"><el-radio-button v-for="(item,index) in materialList" :key="index"  :label="item.name"><div><el-image style="width: 30px; height: 30px" :src="item.url" fit="contain"></el-image></div><div>{{item.name}}</div></el-radio-button></el-radio-group></div><div id="container"></div>

然后添加点击事件,刚才绘制珠子的时候已经给每个柱子添加了名字,就是bead_+珠子的下标,因此点击的时候就通过这个名字来确认点击到的是哪个珠子

    window.addEventListener( 'click', this.clickBead);
clickBead(event){let mouse = new THREE.Vector2();let x, y;if ( event.changedTouches ) {x = event.changedTouches[ 0 ].pageX;y = event.changedTouches[ 0 ].pageY;} else {x = event.clientX;y = event.clientY;}mouse.x = ( x / window.innerWidth ) * 2 - 1;mouse.y = - ( y / window.innerHeight ) * 2 + 1;let raycaster = new THREE.Raycaster();raycaster.setFromCamera( mouse, this.camera );let intersects = raycaster.intersectObjects( [ this.scene ], true );if(intersects.length>0 && intersects[0].object !== null){let tempBeadName = intersects[0].object.name;let exist = truefor (let i = 0; i < this.resultData.bead.length; i++) {if(tempBeadName === this.resultData.bead[i].beadName){this.resultData.bead[i].beadMaterialName = this.selectedMaterial.namethis.resultData.bead[i].beadMaterialUrl = this.selectedMaterial.urlexist = false}}if(exist){let temp = {beadName:tempBeadName,beadRadius:this.defaultBeadRadius,beadMaterialName:this.selectedMaterial.name,beadMaterialUrl:this.selectedMaterial.url,beadColor:"#FFFFFF"}this.resultData.bead.push(temp)}for (let i = 0; i < this.scene.children.length; i++) {if(tempBeadName === this.scene.children[i].name){const textureLoader = new THREE.TextureLoader();const newTexture = textureLoader.load(this.selectedMaterial.url);this.scene.children[i].material.name = this.selectedMaterial.name;this.scene.children[i].material.map = newTexture;this.scene.children[i].material.needsUpdate = true;}}}},

最终效果如下:

threejs绘制手串

以上包含了所有核心代码,所有代码比较多就不贴了,如果需要可以给我留言。


http://www.mrgr.cn/news/63297.html

相关文章:

  • .net core中间件Polly
  • 软件许可的不同类型
  • Java集合使用注意事项总结
  • 专线物流公共服务平台:数据驱动,标准引领,共创金融双赢新时代
  • Python 实现斐波那契数列的方法
  • Servlet 3.0 新特性全解
  • [KTM2802-FP6]气缸位置检测芯片,支持两线/三线气缸位置检测,将AMR传感器和ASIC集成在一个芯片中,国产品牌可信赖
  • GBDT 算法的原理推导
  • 【综合算法学习】(第十三篇)
  • java枚举高级用法
  • Ubuntu20.04版本安装pytorch(宝宝级攻略)
  • FineReport 超级链接
  • 入行网络安全需要学习哪些知识点?白帽子佬都给你汇总在这里,一文全懂_网络安全入门应该学什么
  • huggingface利用bert-base-chinese实现中文情感分类
  • 从倍压整流到二极管钳位与限幅
  • Agent 大模型与应用场景之间的桥梁
  • 4路CAN转WiFi网关
  • Caffeine缓存库的LoadingCache:缓存计算或查询结果
  • Verilog HDL学习记录(3~4章)
  • PMP每日一练(二十一)
  • Spring Boot JPA中的Page组件详解
  • JavaScript 入门指南
  • 1. 让我们聊聊 Netty:高性能网络通信库
  • Tita:什么是 360 评估?
  • 计算机低能儿从0刷leetcode | 34.在排序数组中查找元素的第一个和最后一个位置 | 二分法
  • .net 在线客服系统,到底能不能处理 50万 级消息量,系统架构实践