三维数据图表

53 阅读1分钟

1.搭建3d坐标轴

利用BufferGeometry创建出平面,分别作为左侧,下侧,后侧的平面坐标轴

class GridHelper extends THREE.LineSegments {
    constructor(
    // 传入平面坐标轴的x,y
    sizeX = 1,
    sizeY = 1,
    // 边缘颜色
    color1,
    color2
    )
    // 坐标轴单位为1
    const step = 1
    // 最大长度的一半
    const halfSizeX = sizeX / 2
    const halfSizeY = sizeY / 2
    
    // 坐标数组
    const vertices = []
    // 颜色数组
    const colors = []
    // 声明颜色索引
    let j = 0
    
    // 每条线的两个对应的顶点坐标的Z坐标(Y坐标)不变,X轴单调递增step,创建坐标轴平面的竖线
    for(let i = 0, k = -halfSizeX; i < sizeX; i++, k +=step){
        // x坐标的最小值为-halfSizeX,中间为0
        // z坐标都为 -halfSizeY,-halfSizeY
        vertices.push(k,0,-halfSizeY, k,0,-halfSizeY)
        // 边缘线条颜色为color1,中间的线条为color2
        const color = i == 0 || i == sizeX ? color2 : color1
        // push进数组
        color.toArray(colors, j)
        j+=3
        color.toArray(colors, j)
        j+=3

    }
    
    // 每条线对应的两个x坐标不变,z坐标(y坐标)单调递增step,创建坐标轴平面的横线
    for(let i = 0,k = -halfSizeY; i < sizeY; i++,k+=step){
        vertices.push(-halfSizeX,0,k,halfSizeX,0,k)
        const color = i == 0 || i == sizeY ? color2 : color1;
       color.toArray(colors, j);
      j += 3;
      color.toArray(colors, j);
      j += 3;
    }
    // 利用顶点数组与颜色数组创建出坐标轴平面
    const geometry = new THREE.BufferGeometry()
    geometry.setAttribute(
    'position',
    new THREE.Float32BufferAttribute(vertices, 3)
    )
    geometry.setAttribute(
        'color',
        new THREE.Float32BufferAttribute(colors,3)
    )
    const material = new THREE.LineBasicMaterial({
        vertexColors : true,
        toneMapped : false
    })
    this.type = "GridHelper";
}

2.创建圆柱条形图

class Bar3d(){
    constructor(data,color){
        this.color = color || new THREE.Color(Math.random() * 0xffffff)
        this.material = new THREE.MeshStandardMaterial({
            color: this.color,
            transparent : true,
            opacity : 0.8
        })
        // 创建mesh统一管理
        this.mesh = new THREE.Group();
    // 遍历数据创建几何体
    data.forEach((item,index)=>{
    // 传入上下圆的半径,和高度也就是该项数据的值
        let cylinderGeometry = new THREE.CylinderGeometry(0.5,0.5,item.value)
        let cylinder = new THREE.Mesh(cylinderGeometry, material);
        // 位置 x坐标:-3 -1 1 3 y坐标: item.value / 2 ,往上提一半
        cylinder.position.set(-3 + index * 2, item.value / 2, 0);
        this.mesh.add(cylinder);
    })
    //   添加字体精灵
      // 位置跟对应的圆柱体一样,只是往下挪了0.5
      let textPosition = new THREE.Vector3(-3 + index * 2, item.value + 0.5, 0);
      // 生成精灵图
      let spriteText = new SpriteText(item.name, textPosition);
      this.mesh.add(spriteText.mesh);
    }
}