欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Echarts 巧妙解决视觉映射代替图例展示,并且根据数据大小有序排列深浅颜色的问题

程序员文章站 2022-05-06 10:08:45
...

改造之前的效果图是这样的(图例展示):

Echarts 巧妙解决视觉映射代替图例展示,并且根据数据大小有序排列深浅颜色的问题

改造之后(视觉映射代替图例):

 Echarts 巧妙解决视觉映射代替图例展示,并且根据数据大小有序排列深浅颜色的问题

——————————————————分割线————————————————————

完整这些操作的关键点有如下几点:

1、首先根据echarts文档画出地图,这里要注意的是右边图例的数据要与左边地图坐标产生对应关系,如果右边图例的顺序是固定的也就简单了,直接获取根据data数据的索引值来匹配坐标,但如果拿到的数据顺序不固定,或者还需要对数据的顺序进行加工,那么就不能单纯的使用索引值来匹配了,我这里使用的是通过value值排序:

var geoCoordMap = {
    '兴化市': [119.840162, 32.938065],
    '海陵区': [119.920187, 32.488406],
    '姜堰区': [120.148208, 32.508483],
    '高港区': [119.88166, 32.315701],
    '泰兴市': [120.020228, 32.168784],
    '靖江市': [120.26825, 32.018168]
}
// 默认展示的数据
var data = [
    { name: '兴化市', value: 0 },
    { name: '海陵区', value: 0 },
    { name: '姜堰区', value: 0 },
    { name: '高港区', value: 0 },
    { name: '泰兴市', value: 0 },
    { name: '靖江市', value: 0 }
]
// 决定数据与地图上的对应关系
var convertData = function (data, str) {
    var res = []
    var geoCoord = geoCoordMap[str]
    var vNum
    for (var i = 0; i < data.length; i++) {
      if (data[i].name === str) {
        vNum = data[i].value
      }
    }
    if (geoCoord) {
      res.push({
        name: str,
        value: geoCoord.concat(vNum)
      })
    }
    return res
}

//使用时直接调用上面的函数并传入data和需要对应的区域名称
{
    name: '靖江市',
    type: 'effectScatter',
    coordinateSystem: 'geo',
    symbol: 'circle',
    symbolSize: function (val) {
      return val[2] * scaleNum    //这里是动态进行缩放,后面会分析
    },
    rippleEffect: {
      period: 8,
      scale: 5
    },
    label: {
      normal: {
        show: true,
        offset: [20, -10],
        rotate: 20
      }
    },
    zlevel: 6,
    data: convertData(data, '靖江市')  //这里的数据就是涟漪图的数据
}

2、配置图例之前对获取到的data数据进行排序:

// 对data进行排序
data.sort((a, b) => {
    return b.value - a.value
})

数组调用.sort的API会对改变原数组,所以这里都不需要接收返回值就可以直接对原数组排序。

排序过后在把这些数据挂到echarts上,那么图例展示的顺序就是按照数值大小排序的顺序。

3、动态显示涟漪图的大小。如果我们设置涟漪图的大小是数据的值的话,那么如果值很小,那么在地图上看不出什么效果,如果值特别大,那么涟漪状的波纹会大到完全覆盖地图,体验效果也极差,所以,能不能根据值得大小使涟漪图能够动态得切换缩放倍数呢?

这里我取整个数据的平均值,然后用(20÷平均值)的方式来得到一个 缩放系数,这就保障了如果值都比较小,那么这个缩放系数就很大,如果值都偏大,那么这个缩放系数就比较小,这里有个坑是计算平均值时要排除值为0的数据:

 

// 求data中value的平均值,确定缩放比例
var sum = 0
var length = 0
for (var i = 0; i < data.length; i++) {
    if (data[i].value > 1) {
      length++
      sum += parseInt(data[i].value)
    }
}
var averageNum = sum / (length || 1)
var scaleNum = (20 / (averageNum || 1)).toFixed(2)

这些工作完成之后效果图就如改造前的图展示的效果了,但是UI又提出一个需求,就是图例部分的颜色能不能也根据值得大小做出排序,也就是值最大的永远显示深红色,然后颜色从上到下依次变为绿色。仔细钻研echarts官方配置文档后,发现“视觉映射”貌似可以完成相关的操作:

// 视觉映射
visualMap: {
  type: 'piecewise',
  splitNumber: 6,
  dimension: 2,
  textStyle: {
    color: '#BCE5FD',
    fontSize: 14
  },
  right: '10%',
  top: '15%',
  itemGap: 30,
  pieces: [
    { value: data[0].value, label: data[0].name + ' ' + (data[0].value | 0), color: '#D01864' },
    { value: data[1].value, label: data[1].name + ' ' + (data[1].value | 0), color: '#E53C19' },
    { value: data[2].value, label: data[2].name + ' ' + (data[2].value | 0), color: '#F0AE1D' },
    { value: data[3].value, label: data[3].name + ' ' + (data[3].value | 0), color: '#D0D85E' },
    { value: data[4].value, label: data[4].name + ' ' + (data[4].value | 0), color: '#A1DE6C' },
    { value: data[5].value, label: data[5].name + ' ' + (data[5].value | 0), color: '#00B15E' }
  ]
},

在pieces中设置视觉分段映射的值就是data中的value值,但是视觉映射这里有一个问题就是如果数值重复那么只会显示其中的一个数组,后来想到一个解决方案就是给排序后的数组中的每一个value加一个小数值,比如0.0001,0.0002之类的,即不会影响平均值的计算,又可以把原本相同的数值给区分开,还要注意的是视觉映射时使用带小数的值,文字展示时可以用“ | 0 ”与0或位运算的方式去掉小数位数,计算平均值时也要去掉小于1的数据以防止偏差过大。

// 给data中的value值加一个小数点,为视觉映射提供支持,如果要加随机值,注意去掉生成的随机数后面的小数
for (var j = 0; j < data.length; j++) {
    data[j].value = parseInt(data[j].value) + parseFloat('0.000' + (6 - j))
}

 

至此,大功告成,既可以根据值大小顺序展示图例,又可以根据值的大小顺序展示颜色,图例与涟漪图还有颜色对应关系,涟漪图还根据数值大小及范围动态缩放。

Echarts 巧妙解决视觉映射代替图例展示,并且根据数据大小有序排列深浅颜色的问题