vue2+echart热力气泡图

206 阅读1分钟

实现需求

需要显示两两指标交叉得到的corr和sig数,且数字的绝对值越大,颜色越深,气泡越大。同时鼠标移上去能显示这两个数的弹框,效果如下所示:

f09c52c1d0de319b615e80a959b1178.png

实现思路

采用echart散点图方式实现,横坐标隐藏,用div和css写出渐变效果,需要注意的是热力气泡图的数据是二维数组,需严格按照显示内容组装数据

    [
        "分娩率",
        "分娩率",
        "",
        "分娩率"
    ],
    [
        "平均非生产天数",
        "平均非生产天数",
        "",
        "平均非生产天数"
    ],
    [
        "分娩率",
        "平均非生产天数",
        "0.0000",
        "-0.53"
    ],
    [
        "窝均活仔数",
        "窝均活仔数",
        "",
        "窝均活仔数"
    ],
    [
        "分娩率",
        "窝均活仔数",
        "0.0000",
        "0.16"
    ],
    [
        "平均非生产天数",
        "窝均活仔数",
        "0.0765",
        "-0.05"
    ]
]
// echart
export function hotScatterChart(datas) {
  return {
    grid: {
      top: fontSize(20),
      bottom: fontSize(2),
      left: fontSize(0),
      right:fontSize(3)
    },
    tooltip: {
      extraCssText: 'padding-right:8px;padding-left:8px;line-height:30px;background:rgba(255,255,255,1);box-shadow:1px 5px 20px 0px rgba(1,11,19,0.2);border-radius:6px;',
      formatter: function(obj) {
        var value = obj.value;
        let star = '';
        if (value[2] < 0.05 && (value[2] > 0.01 || value[2] == 0.01)) {
          star = '*'
        } else if (value[2] < 0.01 && (value[2] > 0.001 || value[2] == 0.001)) {
          star = '**'
        } else if(value[2] < 0.001) {
          star = '***'
        }
        if (value[3] != value[0]) {
          const indexOne = $t(value[0])
          const indexTwo = $t(value[1])
          const sigVal = value[2]
          return `<div class="hotTool">【${indexOne}, ${indexTwo}】</div>
                  <p class="hotTool">
                    <span>Corr相关关系:</span>
                    <span class="hotTool-val">${value[3]}${star}</span>
                  </p>
                  <p class="hotTool">
                    <span>Sig(显著性研究成果):</span>
                    <span class="hotTool-val">${sigVal}</span>
                  </p>`
        }
      }
    },
    xAxis: {
        position: 'top',
        type: 'category',
        axisLine: {
          lineStyle: {
            color: '#eee',
          }
        },
        axisTick: {
          show: false
        },
        splitLine: {
          show: true,
          lineStyle: {
            color: '#eee'
          }
        },
        axisLabel: {
          show: false
        }
    },
    yAxis: {
        type: 'category',
        inverse: true,
        splitLine: {
          show: true,
          lineStyle: {
            color: '#eee'
          }
        },
        axisTick: {
          show: false
        },
        axisLine: {
          lineStyle: {
            color: '#eee',
          }
        },
        axisLabel: {
          show: false
        }
    },
    visualMap: {
        type: 'continuous',
        max: 1,
        min: -1,
        inRange: {
          color: ['#0062FF', '#FDE7FF', '#FF4C28']
        },
        show: false,
    },
    series: [{
        type: 'scatter',
        symbolSize: function(data) {
          if (data[3] == '0.0') {
            return Math.sqrt(Math.abs(0.01) ) * 35;
          } else {
            return Math.sqrt(Math.abs(data[3]) ) * 35;
          }
        },
        data: datas,
        label: {
          textStyle: {
            fontSize: fontSize(16), //字体大小
          },
          formatter: function(params) {
            if(params.value[0] ==  params.value[1]) {
              let indexName = params.value[0]
              const language = localStorage.getItem('currentLanguage')
              if ((indexName.length > 15 && language == 'en-US') && datas.length > 27) {
                const name = indexName.substring(0, 15) + '...'
                return "{font|" + name + "}";
              } else {
                return "{font|" + $t(params.value[0]) + "}";
              }
            } else {
              return "{num|" +  params.value[3] + "}";
            }
          },
          rich: {
            font: {
              color: '#333',
              fontSize: fontSize(16),
            },
            num: {
              color: '#fff',
              fontSize: fontSize(14),
            },
          },
          show: true
        }
    }]
  };
}