three.js 模仿区块链 实现多个小球互相连接
实现原理
利用SphereGeometry先随机生成一个大点的类圆球,取其顶点。 根据顶点数量,生成小球个数,每个小球的位置定位为顶点数据,至此所有小球生成完毕。 两点一线,同理,两个小球的定位位置相连,既是小球相连。根据特定设计算法,设置小球相连关系。复制代码
步骤一 生成小球
根据顶点数据生成一系列的小球 addSingleSphereGeometry(position) { var geometry = new THREE.SphereBufferGeometry( 7, 32, 32 ); var material = new THREE.MeshBasicMaterial( {color: '#949494'} ); var sphere = new THREE.Mesh( geometry, material ); sphere.name = position.name; sphere.isLine = position.isLine; sphere.position.set(position.x, position.y, position.z) this.scene.add( sphere ); }复制代码
步骤二 两个小球相连--连线
根据两个小球定位的位置,两个顶点相连 addSingleLineGeometry(points) { let vectors = []; points.forEach(item => { vectors = vectors.concat([item.x, item.y, item.z]) }) const lineGeometry = new THREE.BufferGeometry(); lineGeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vectors, 3 ) ); const lineMaterial = new THREE.LineBasicMaterial( { color: 0xffffff, // lineWidth: 3 由于OpenGL Core Profile与 大多数平台上WebGL渲染器的限制,无论如何设置该值,线宽始终为1。 }); let object = new THREE.Line( lineGeometry, lineMaterial ); this.scene.add(object) // this.group.add(object); }复制代码
步骤三 设计小球顶点数据格式,小球间连接关系
以下是设计的部分数据, x,y,z--顶点信息,既是生成小球的定位位置 origin: 小球连线的起始位置。表示数据是该顶点再顶点数组中的下标。 end: 小球连接的终端位置,如有多个,既表示该小球与多个小球相连。表示数据是终端位置顶点再顶点数组中的下标。 isLine: true--表示画线, false--表示不画线 name: 顶点名称,亦可表示其他数据,用作记录小球的特性,方便做一些操作。 vectors_data = [{x: -0, y: 120, z: 0, origin: 0, end: [1,2,3,4,5,6,7,8], isLine: true, name: '0-0'}, {x: -45.92201232910156, y: 110.86554718017578, z: 0, origin: 1, end: [2, 9], isLine: true, name: '0-1'}, {x: -32.47176742553711, y: 110.86554718017578, z: 32.47176742553711, origin: 2, end: [3, 10], isLine: true, name: '0-2'}, {x: -2.811912215659046e-15, y: 110.86554718017578, z: 45.92201232910156, origin: 3, end: [4, 11], isLine: true, name: '0-3'}, {x: 32.47176742553711, y: 110.86554718017578, z: 32.47176742553711, origin: 4, end: [5, 12], isLine: true, name: '0-4'}, {x: 45.92201232910156, y: 110.86554718017578, z: 5.623824431318092e-15, origin: 5, end: [6, 13], isLine: true, name: '0-5'}, {x: 32.47176742553711, y: 110.86554718017578, z: -32.47176742553711, origin: 6, end: [7, 14], isLine: true, name: '0-6'}, {x: 8.435736646977138e-15, y: 110.86554718017578, z: -45.92201232910156, origin: 7, end: [8, 15], isLine: true, name: '0-7'}, {x: -32.47176742553711, y: 110.86554718017578, z: -32.47176742553711, origin: 8, end: [1, 16], isLine: true, name: '0-8'}, {x: -84.85281372070312, y: 84.85281372070312, z: 0, origin: 9, end: [10, 17], isLine: true, name: '0-9'}, {x: -60, y: 84.85281372070312, z: 60, origin: 10, end: [11, 18], isLine: true, name: '0-10'}, {x: -5.19573652087461e-15, y: 84.85281372070312, z: 84.85281372070312, origin: 11, end: [12, 19], isLine: true, name: '0-11'}, {x: 60, y: 84.85281372070312, z: 60, origin: 12, end: [13, 20], isLine: true, name: '0-12'}, {x: 84.85281372070312, y: 84.85281372070312, z: 1.039147304174922e-14, origin: 13, end: [14, 21], isLine: true, name: '0-13'}, {x: 60, y: 84.85281372070312, z: -60, origin: 14, end: [15, 22], isLine: true, name: '0-14'}, {x: 1.5587208715590883e-14, y: 84.85281372070312, z: -84.85281372070312, origin: 15, end: [16, 23], isLine: true, name: '0-15'}, {x: -60, y: 84.85281372070312, z: -60, origin: 16, end: [9, 24], isLine: true, name: '0-16'}] initSphereAndLine() { vectors_data.forEach(item => { this.addSingleSphereGeometry(item) }) vectors_data.forEach(item => { if(item.isLine) { item.end.forEach(i => { let tempArr = []; tempArr.push(vectors_data[item.origin]) tempArr.push(vectors_data[i]) console.log(tempArr) this.addSingleLineGeometry(tempArr) }) } }) } 复制代码
步骤四 监听点击事件,被点击小球,设置成红色
document.addEventListener( 'click', this.mouseClick, false ); mouseClick(event) { var mouse = new THREE.Vector2(); mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1; mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1; this.raycaster.setFromCamera( mouse, this.camera ); var intersects = this.raycaster.intersectObjects( this.scene.children, false ); for ( var i = 0; i < intersects.length; i++ ) { if(intersects[i].face) { intersects[ i ].object.material.color.set( 0xff0000 ); } } } 复制代码
备注:基本交互已经实现,点击可以知道选中的小球,做出对应的操作即可。代码非完整的,整体思路既是这样实现的。
作者:大厨学WebGL
链接:https://juejin.cn/post/7032201462524575775