通过echarts的平面画出3D立体效果 js逻辑

530 阅读7分钟

实现前平面.png

效果:

3D.png

echarts 的平面有点恶心的地方 就是坐标必须对应 比如x轴有10列 y轴10行 就必须得对应着 类似魔方的一个面 一个坐标轴不对就会渲染不出来

微信图片_20211118141612.png

var sj = [ [96, 12, 770], [280, 12, 764.9], [464, 12, 755.5], [648, 12, 748], [832, 12, 740.7], [1016, 12, 735.3], [1200, 12, 503.2], [1384, 12, 670.3], [1568, 12, 669.4], [1752, 12, 668.4], [1936, 12, 667.5], [2120, 12, 666.6], [2304, 12, 665.7], [96, 196, 751.7], [280, 196, 743.6], [464, 196, 736.4], [648, 196, 724.5], [832, 196, 719.6], [1016, 196, 713.2], [1200, 196, 701.6], [1384, 196, 664.7], [1568, 196, 666.7], [1752, 196, 662.9], [1936, 196, 664.1], [2120, 196, 663.9], [2304, 196, 668.4], [96, 380, 729.8], [280, 380, 719.2], [464, 380, 714.9], [648, 380, 710.2], [832, 380, 709.9], [1016, 380, 703.7], [1200, 380, 666.5], [1384, 380, 675.7], [1568, 380, 675.1], [1752, 380, 669.4], [1936, 380, 674.9], [2120, 380, 670.6], [2304, 380, 671.1], [96, 564, 728.2], [280, 564, 714.8], [464, 564, 712], [648, 564, 708.3], [832, 564, 708], [1016, 564, 502.3], [1200, 564, 667.9], [1384, 564, 675.9], [1568, 564, 683.3], [1752, 564, 678.1], [1936, 564, 676.7], [2120, 564, 675.9], [2304, 564, 673.8], [96, 748, 726.6], [280, 748, 721.6], [464, 748, 715.8], [648, 748, 706], [832, 748, 707.1], [1016, 748, 702], [1200, 748, 682.1], [1384, 748, 687.6], [1568, 748, 688.7], [1752, 748, 687.2], [1936, 748, 682.4], [2120, 748, 683.7], [2304, 748, 676.5], [96, 932, 725], [280, 932, 714.6], [464, 932, 709.5], [648, 932, 704.1], [832, 932, 702.9], [1016, 932, 704.7], [1200, 932, 691.2], [1384, 932, 694.9], [1568, 932, 695.9], [1752, 932, 492.2], [1936, 932, 687], [2120, 932, 685.4], [2304, 932, 679.3], [96, 1116, 723.4], [280, 1116, 709.5], [464, 1116, 707.2], [648, 1116, 705.4], [832, 1116, 701.9], [1016, 1116, 699.5], [1200, 1116, 697.1], [1384, 1116, 700.9], [1568, 1116, 699.1], [1752, 1116, 698.1], [1936, 1116, 692.9], [2120, 1116, 691.6], [2304, 1116, 682], [96, 1300, 721.8], [280, 1300, 708.6], [464, 1300, 707.8], [648, 1300, 704.5], [832, 1300, 702.3], [1016, 1300, 696.6], [1200, 1300, 495.8], [1384, 1300, 701.4], [1568, 1300, 699.3], [1752, 1300, 499], [1936, 1300, 696], [2120, 1300, 692.8], [2304, 1300, 684.7], [96, 1484, 710], [280, 1484, 707.7], [464, 1484, 706.7], [648, 1484, 703.9], [832, 1484, 702.1], [1016, 1484, 701.9], [1200, 1484, 702.2], [1384, 1484, 700.5], [1568, 1484, 697.7], [1752, 1484, 694.4], [1936, 1484, 688.9], [2120, 1484, 687.9], [2304, 1484, 513.1], [96, 1668, 711.9], [280, 1668, 705.7], [464, 1668, 705.7], [648, 1668, 706.7], [832, 1668, 702.4], [1016, 1668, 707.2], [1200, 1668, 707.8], [1384, 1668, 695.3], [1568, 1668, 692.4], [1752, 1668, 687], [1936, 1668, 684], [2120, 1668, 716.6], [2304, 1668, 717.5], [96, 1852, 713.8], [280, 1852, 708.1], [464, 1852, 706.5], [648, 1852, 707.6], [832, 1852, 507.3], [1016, 1852, 704.6], [1200, 1852, 709.2], [1384, 1852, 682.5], [1568, 1852, 685.2], [1752, 1852, 684.9], [1936, 1852, 677.4], [2120, 1852, 721], [2304, 1852, 721.8], [96, 2036, 715.6], [280, 2036, 710.2], [464, 2036, 696.8], [648, 2036, 709.7], [832, 2036, 710.2], [1016, 2036, 706.4], [1200, 2036, 709.8], [1384, 2036, 673.5], [1568, 2036, 478], [1752, 2036, 679.4], [1936, 2036, 679.3], [2120, 2036, 725.3], [2304, 2036, 726.2], [96, 2220, 717.5], [280, 2220, 711.7], [464, 2220, 710.7], [648, 2220, 712], [832, 2220, 711.8], [1016, 2220, 712.7], [1200, 2220, 712], [1384, 2220, 671.7], [1568, 2220, 682.5], [1752, 2220, 690.3], [1936, 2220, 700.6], [2120, 2220, 709.1], [2304, 2220, 730.5], [96, 2404, 719.3], [280, 2404, 718.4], [464, 2404, 718.2], [648, 2404, 717.1], [832, 2404, 716.7], [1016, 2404, 711.4], [1200, 2404, 710.5], [1384, 2404, 711.1], [1568, 2404, 719.5], [1752, 2404, 726.5], [1936, 2404, 731.5], [2120, 2404, 740.3], [2304, 2404, 745], [96, 2588, 521.2], [280, 2588, 720.2], [464, 2588, 731.2], [648, 2588, 718.3], [832, 2588, 717.4], [1016, 2588, 716.4], [1200, 2588, 715.4], [1384, 2588, 741.6], [1568, 2588, 750.7], [1752, 2588, 750.8], [1936, 2588, 760.3], [2120, 2588, 762.1], [2304, 2588, 726], ];

实现思路 还是拿魔方举例 比如获得的是9宫格魔方的一面 就是9个坐标点 但是你要把他画出来实现高度 我的实现是给它向外围再加一层 把面变成4*4

然后要注意的是 以魔方为例 它其实是加了12个点 有4个角是共用的

我先实现获得x、y’轴的最大、最小值
话不多说上代码

  var y =  sj.map(item => {
    return item[1]
  })
  var x =  sj.map(item => {
    return item[0]
  })

  var bcfy = [...new Set(y)]

  var bcfx = [...new Set(x)]

  // console.log(tempObj)
  var maxy = y[0] // 数组中的最大值
  var miny = y[0] // 数组中的最小值
  var mosty // 数组中出现次数最多的元素
  var tempObj = {}
  var num = 0
  for (var i = y.length; i >= 0; i--) {
    if (maxy < y[i]) {
      // 得到最大值
      maxy = y[i]
    }
    if (miny > y[i]) {
      // 得到最小值
      miny = y[i]
    }
    if (tempObj[y[i]]) {
      // 得到元素出现的次数,并组成obj
      tempObj[y[i]] = tempObj[y[i]] + 1
    } else {
      tempObj[y[i]] = 1
    }
  }

  var maxx = x[0] // 数组中的最大值
  var minx = x[0] // 数组中的最小值
  var mostx // 数组中出现次数最多的元素
  var tempObj = {}
  var num = 0
  for (var i = x.length; i >= 0; i--) {
    if (maxx < x[i]) {
      // 得到最大值
      maxx = x[i]
    }
    if (minx > x[i]) {
      // 得到最小值
      minx = x[i]
    }
    if (tempObj[x[i]]) {
      // 得到元素出现的次数,并组成obj
      tempObj[x[i]] = tempObj[x[i]] + 1
    } else {
      tempObj[x[i]] = 1
    }

    // console.log(mosty)
  }

和最外层x、y轴的坐标点

再然后把获得x、y的最大值加1,最小值减1 把y的最大、小加1的值push到上面获得的最外层y轴坐标点里

for循环新y轴坐标 在循环里把x轴的最大、小 分别加到y轴的坐标点上

  maxy += 1
  miny -= 1
  maxx += 1
  minx -= 1
  bcfx.unshift(minx)
  bcfx.push(maxx)
  // bcfy.unshift(miny)
  // bcfy.push(maxy)

  var minxsz = [] //x轴最小
  var maxxsz = [] //x轴最大
  var minysz = [] //y轴最小
  var maxysz = [] //y轴最大
  for (var i = 0; i < bcfx.length; i++) {
    // y轴 前后增加
    minxsz.push([bcfx[i], miny, -1])
    maxxsz.push([bcfx[i], maxy, -1])
  }

  sj.unshift(...minxsz)
  sj.push(...maxxsz)
  var sunlei = sj.map(item => {
    return item[1]
  })

  var sun = []
  var lei = []
  for (var i = 0; i < bcfy.length; i++) {
    minysz.push([minx, bcfy[i], -1])
    maxysz.push([maxx, bcfy[i], -1])
    lei.push(sunlei.map(o => o).lastIndexOf(bcfy[i]) * 1 + 1)
  }
  minysz = minysz.reverse()
  maxysz = maxysz.reverse()
  lei = lei.reverse()

把它Z轴新增的外围设置成-1 过了3个月了 后面为啥这么写想不起来了

  for (var i = 0; i < lei.length; i++) {
    sj.splice(lei[i], 0, maxysz[i])
  }
  var er = sj.map(item => {
    return item[1]
  })
  for (var i = 0; i < bcfy.length; i++) {
    sun.push(er.map(o => o).indexOf(bcfy[i]) * 1)
  }
  sun = sun.reverse()
  for (var i = 0; i < sun.length; i++) {
    sj.splice(sun[i], 0, minysz[i])
  }

最后放上代码
需要引入的js文件 记得要引入啊

<html>

<head>
    <meta charset="utf-8">
    <title>Grid3D - ECHARTS-GL</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
    <meta name="apple-mobile-web-app-capable" content="yes"> <!-- Fullscreen Landscape on iOS -->
    <link rel="stylesheet" href="./common.css">
</head>

<body>
    <div id="main"></div>
    <script src="./echarts.js"></script>
    <script src="./echarts-gl.js"></script>
    <script src="jquery.min.js"></script>
    <script src="commonUI.js"></script>
    <script>
        var chart = echarts.init(document.getElementById('main'));
//   sj是通过接口来获得 的检测到的坐标
        var sj = [
            [96, 12, 770],
            [280, 12, 764.9],
            [464, 12, 755.5],
            [648, 12, 748],
            [832, 12, 740.7],
            [1016, 12, 735.3],
            [1200, 12, 503.2],
            [1384, 12, 670.3],
            [1568, 12, 669.4],
            [1752, 12, 668.4],
            [1936, 12, 667.5],
            [2120, 12, 666.6],
            [2304, 12, 665.7],
            [96, 196, 751.7],
            [280, 196, 743.6],
            [464, 196, 736.4],
            [648, 196, 724.5],
            [832, 196, 719.6],
            [1016, 196, 713.2],
            [1200, 196, 701.6],
            [1384, 196, 664.7],
            [1568, 196, 666.7],
            [1752, 196, 662.9],
            [1936, 196, 664.1],
            [2120, 196, 663.9],
            [2304, 196, 668.4],
            [96, 380, 729.8],
            [280, 380, 719.2],
            [464, 380, 714.9],
            [648, 380, 710.2],
            [832, 380, 709.9],
            [1016, 380, 703.7],
            [1200, 380, 666.5],
            [1384, 380, 675.7],
            [1568, 380, 675.1],
            [1752, 380, 669.4],
            [1936, 380, 674.9],
            [2120, 380, 670.6],
            [2304, 380, 671.1],
            [96, 564, 728.2],
            [280, 564, 714.8],
            [464, 564, 712],
            [648, 564, 708.3],
            [832, 564, 708],
            [1016, 564, 502.3],
            [1200, 564, 667.9],
            [1384, 564, 675.9],
            [1568, 564, 683.3],
            [1752, 564, 678.1],
            [1936, 564, 676.7],
            [2120, 564, 675.9],
            [2304, 564, 673.8],
            [96, 748, 726.6],
            [280, 748, 721.6],
            [464, 748, 715.8],
            [648, 748, 706],
            [832, 748, 707.1],
            [1016, 748, 702],
            [1200, 748, 682.1],
            [1384, 748, 687.6],
            [1568, 748, 688.7],
            [1752, 748, 687.2],
            [1936, 748, 682.4],
            [2120, 748, 683.7],
            [2304, 748, 676.5],
            [96, 932, 725],
            [280, 932, 714.6],
            [464, 932, 709.5],
            [648, 932, 704.1],
            [832, 932, 702.9],
            [1016, 932, 704.7],
            [1200, 932, 691.2],
            [1384, 932, 694.9],
            [1568, 932, 695.9],
            [1752, 932, 492.2],
            [1936, 932, 687],
            [2120, 932, 685.4],
            [2304, 932, 679.3],
            [96, 1116, 723.4],
            [280, 1116, 709.5],
            [464, 1116, 707.2],
            [648, 1116, 705.4],
            [832, 1116, 701.9],
            [1016, 1116, 699.5],
            [1200, 1116, 697.1],
            [1384, 1116, 700.9],
            [1568, 1116, 699.1],
            [1752, 1116, 698.1],
            [1936, 1116, 692.9],
            [2120, 1116, 691.6],
            [2304, 1116, 682],
            [96, 1300, 721.8],
            [280, 1300, 708.6],
            [464, 1300, 707.8],
            [648, 1300, 704.5],
            [832, 1300, 702.3],
            [1016, 1300, 696.6],
            [1200, 1300, 495.8],
            [1384, 1300, 701.4],
            [1568, 1300, 699.3],
            [1752, 1300, 499],
            [1936, 1300, 696],
            [2120, 1300, 692.8],
            [2304, 1300, 684.7],
            [96, 1484, 710],
            [280, 1484, 707.7],
            [464, 1484, 706.7],
            [648, 1484, 703.9],
            [832, 1484, 702.1],
            [1016, 1484, 701.9],
            [1200, 1484, 702.2],
            [1384, 1484, 700.5],
            [1568, 1484, 697.7],
            [1752, 1484, 694.4],
            [1936, 1484, 688.9],
            [2120, 1484, 687.9],
            [2304, 1484, 513.1],
            [96, 1668, 711.9],
            [280, 1668, 705.7],
            [464, 1668, 705.7],
            [648, 1668, 706.7],
            [832, 1668, 702.4],
            [1016, 1668, 707.2],
            [1200, 1668, 707.8],
            [1384, 1668, 695.3],
            [1568, 1668, 692.4],
            [1752, 1668, 687],
            [1936, 1668, 684],
            [2120, 1668, 716.6],
            [2304, 1668, 717.5],
            [96, 1852, 713.8],
            [280, 1852, 708.1],
            [464, 1852, 706.5],
            [648, 1852, 707.6],
            [832, 1852, 507.3],
            [1016, 1852, 704.6],
            [1200, 1852, 709.2],
            [1384, 1852, 682.5],
            [1568, 1852, 685.2],
            [1752, 1852, 684.9],
            [1936, 1852, 677.4],
            [2120, 1852, 721],
            [2304, 1852, 721.8],
            [96, 2036, 715.6],
            [280, 2036, 710.2],
            [464, 2036, 696.8],
            [648, 2036, 709.7],
            [832, 2036, 710.2],
            [1016, 2036, 706.4],
            [1200, 2036, 709.8],
            [1384, 2036, 673.5],
            [1568, 2036, 478],
            [1752, 2036, 679.4],
            [1936, 2036, 679.3],
            [2120, 2036, 725.3],
            [2304, 2036, 726.2],
            [96, 2220, 717.5],
            [280, 2220, 711.7],
            [464, 2220, 710.7],
            [648, 2220, 712],
            [832, 2220, 711.8],
            [1016, 2220, 712.7],
            [1200, 2220, 712],
            [1384, 2220, 671.7],
            [1568, 2220, 682.5],
            [1752, 2220, 690.3],
            [1936, 2220, 700.6],
            [2120, 2220, 709.1],
            [2304, 2220, 730.5],
            [96, 2404, 719.3],
            [280, 2404, 718.4],
            [464, 2404, 718.2],
            [648, 2404, 717.1],
            [832, 2404, 716.7],
            [1016, 2404, 711.4],
            [1200, 2404, 710.5],
            [1384, 2404, 711.1],
            [1568, 2404, 719.5],
            [1752, 2404, 726.5],
            [1936, 2404, 731.5],
            [2120, 2404, 740.3],
            [2304, 2404, 745],
            [96, 2588, 521.2],
            [280, 2588, 720.2],
            [464, 2588, 731.2],
            [648, 2588, 718.3],
            [832, 2588, 717.4],
            [1016, 2588, 716.4],
            [1200, 2588, 715.4],
            [1384, 2588, 741.6],
            [1568, 2588, 750.7],
            [1752, 2588, 750.8],
            [1936, 2588, 760.3],
            [2120, 2588, 762.1],
            [2304, 2588, 766],
        ];
      var y =  sj.map(item => {
        return item[1]
      })
      var x =  sj.map(item => {
        return item[0]
      })
  
      var bcfy = [...new Set(y)]

      var bcfx = [...new Set(x)]

      // console.log(tempObj)
      var maxy = y[0] // 数组中的最大值
      var miny = y[0] // 数组中的最小值
      var mosty // 数组中出现次数最多的元素
      var tempObj = {}
      var num = 0
      for (var i = y.length; i >= 0; i--) {
        if (maxy < y[i]) {
          // 得到最大值
          maxy = y[i]
        }
        if (miny > y[i]) {
          // 得到最小值
          miny = y[i]
        }
        if (tempObj[y[i]]) {
          // 得到元素出现的次数,并组成obj
          tempObj[y[i]] = tempObj[y[i]] + 1
        } else {
          tempObj[y[i]] = 1
        }
      }

      var maxx = x[0] // 数组中的最大值
      var minx = x[0] // 数组中的最小值
      var mostx // 数组中出现次数最多的元素
      var tempObj = {}
      var num = 0
      for (var i = x.length; i >= 0; i--) {
        if (maxx < x[i]) {
          // 得到最大值
          maxx = x[i]
        }
        if (minx > x[i]) {
          // 得到最小值
          minx = x[i]
        }
        if (tempObj[x[i]]) {
          // 得到元素出现的次数,并组成obj
          tempObj[x[i]] = tempObj[x[i]] + 1
        } else {
          tempObj[x[i]] = 1
        }

        // console.log(mosty)
      }
      maxy += 1
      miny -= 1
      maxx += 1
      minx -= 1
      bcfx.unshift(minx)
      bcfx.push(maxx)
      // bcfy.unshift(miny)
      // bcfy.push(maxy)

      var minxsz = [] //x轴最小
      var maxxsz = [] //x轴最大
      var minysz = [] //y轴最小
      var maxysz = [] //y轴最大
      for (var i = 0; i < bcfx.length; i++) {
        // y轴 前后增加
        minxsz.push([bcfx[i], miny, -1])
        maxxsz.push([bcfx[i], maxy, -1])
      }

      sj.unshift(...minxsz)
      sj.push(...maxxsz)
      var sunlei = sj.map(item => {
        return item[1]
      })

      var sun = []
      var lei = []
      for (var i = 0; i < bcfy.length; i++) {
        minysz.push([minx, bcfy[i], -1])

        maxysz.push([maxx, bcfy[i], -1])

        lei.push(sunlei.map(o => o).lastIndexOf(bcfy[i]) * 1 + 1)
      }
      minysz = minysz.reverse()
      maxysz = maxysz.reverse()
      lei = lei.reverse()

      for (var i = 0; i < lei.length; i++) {
        sj.splice(lei[i], 0, maxysz[i])
      }

      var er = sj.map(item => {
        return item[1]
      })
      for (var i = 0; i < bcfy.length; i++) {
        sun.push(er.map(o => o).indexOf(bcfy[i]) * 1)
      }
      sun = sun.reverse()

      for (var i = 0; i < sun.length; i++) {
        sj.splice(sun[i], 0, minysz[i])
      }
      // this.sj.push(...minysz,...maxxsz,...minysz,...maxysz)ss
   
        chart.setOption({
        // 需要注意的是我们不能跟 grid 一样省略 grid3D
        grid3D: {
          axisLine: {
            lineStyle: { color: '#2ab78c' }
          },
          axisPointer: {
            lineStyle: { color: '#2ab78c' }
          }
        },
        // 默认情况下, x, y, z 分别是从 0 到 1 的数值轴
        xAxis3D: {
          axisLine: {
            lineStyle: { color: '#2ab78c' }
          },
          axisPointer: {
            lineStyle: { color: '#2ab78c' }
          },
          polarIndex: {
            lineStyle: { color: '#2ab78c' }
          }
        },
        yAxis3D: {
          axisLine: {
            lineStyle: { color: '#2ab78c' }
          },
          axisPointer: {
            lineStyle: { color: '#2ab78c' }
          }
        },
        zAxis3D: {
          axisLine: {
            textStyle: { color: '#2ab78c' }
          },
          axisPointer: {
            textStyle: { color: '#2ab78c' }
          },

          max: 3000,
          min: -100,
          type: 'value'
        },
        backgroundColor: '#020806',
        visualMap: [
          {
            show: false,
            dimension: 0, //按照x轴渐变
            min: -100, //TODO需要根据数据动态调整
            max: 3000, //TODO需要根据数据动态调整
            // let mapMax = Math.max(...data.map(item => item[2]));
            // let mapMin = Math.min(...data.map(item => item[2]));
            seriesIndex: 0,
            target: {
              inRange: {
                color: ['rgba(85,253,165,0.7)']
                // color: ['red','green']
              }
            }
          },
          {
            show: false,
            seriesIndex: 1,
            target: {
              inRange: {
                symbolSize: [10, 20],
                color: 'red'
              }
            }
          }
        ],
        series: [
          {
            //type: 'scatter3D',
            //type: 'bar3D',
            type: 'surface',
            data: sj
          },
          {
            type: 'scatter3D',
            // symbol: 'circle',
            symbol:
              'path://M30.9,53.2C16.8,53.2,5.3,41.7,5.3,27.6S16.8,2,30.9,2C45,2,56.4,13.5,56.4,27.6S45,53.2,30.9,53.2z M30.9,3.5C17.6,3.5,6.8,14.4,6.8,27.6c0,13.3,10.8,24.1,24.101,24.1C44.2,51.7,55,40.9,55,27.6C54.9,14.4,44.1,3.5,30.9,3.5z M36.9,35.8c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H36c0.5,0,0.9,0.4,0.9,1V35.8z M27.8,35.8 c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H27c0.5,0,0.9,0.4,0.9,1L27.8,35.8L27.8,35.8z',
            zlevel: 10,
            itemStyle: {
              color: 'black'
            }
            // data:this.sj
          }
        ]
      });

        window.addEventListener('resize', function () {
            chart.resize();
        });
    </script>
</body>

</html>