阅读 445

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 );
    }复制代码

捕获1.PNG

步骤二 两个小球相连--连线

    根据两个小球定位的位置,两个顶点相连
    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);
    }复制代码

捕获2.PNG

步骤三 设计小球顶点数据格式,小球间连接关系

以下是设计的部分数据,
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)
                })
            }
        })
    }        
复制代码

捕获.PNG

步骤四 监听点击事件,被点击小球,设置成红色

    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


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐