首页 前端知识 使用Echarts实现地图展示

使用Echarts实现地图展示

2024-08-12 10:08:56 前端知识 前端哥 172 829 我要收藏

首先来看下效果
在这里插入图片描述
实现其实也简单,创建一个组件

<template>
  <div id="centerBottomMap">
    <div class="bg-color-black">
      <div class="d-flex pt-2 pl-2">
        <span>
          <icon name="map" class="text-icon"></icon>
        </span>
        <span class="fs-xl text mx-2">用户所在城市分布</span>
      </div>
      <div class="d-flex ai-center flex-column body-box">
        <centerMap :cdata="cdata"/>
      </div>
    </div>
  </div>
</template>

<script>
  import centerMap from '@/components/echart/centerMap'
  import {getUserCityData} from "@/api/statistics";

  export default {
  data() {
    return {
      timing: null,
      cdata: {}
    }
  },
  components: {
    centerMap
  },
  mounted() {
    this.getData()
  },
  beforeDestroy () {
  },
  methods:{
    getData() {
      //从后台获取用户城市分布数据
      getUserCityData().then(res => {
        if (res.code === 0) {
          this.cdata = {
            regionCode: 'china',
            data: res.data
          }
          console.info(this.cdata)
        }
      });
    }
  }
}
</script>

<style lang="scss" scoped>
#centerBottomMap {
  $box-height: 440px;
  $box-width: 100%;
  height: $box-height;
  width: $box-width;
  border-radius: 5px;
  padding: 0 16px;
  min-width: $box-width;
  .bg-color-black {
    padding: 5px;
    height: $box-height;
    width: $box-width;
    border-radius: 10px;
  }
  .text {
    color: #c3cbde;
  }
  .body-box {
    border-radius: 10px;
    overflow: hidden;
    .dv-cap-chart {
      width: 100%;
      height: 160px;
    }
  }
}
</style>

后台数据类似这样
在这里插入图片描述
以列表形式返回

然后我们再来看centerMap/index.vue

<template>
  <Echart
    :options="options"
    ref="map"
    height="410px"
    width="680px"/>
</template>

<script>
  import map from '@/common/map'

  export default {
    data() {
      return {
        length: 34,
        options: {},
      };
    },
    props: {
      cdata: {
        type: Object,
        default: () => ({})
      },
    },
    watch: {
      cdata: {
        handler (newData) {
          if (newData !== undefined && newData.data !== undefined) {
            let name = newData.regionCode
            let _data = newData.data

            let mapData = map.mapJson
            this.$echarts.registerMap(name, mapData);
            let cityCenter = {}
            let arr = mapData.features;
            //根据geo json获取省份中心点
            arr.map((item) => {
              cityCenter[item.properties.name] = item.properties.centroid || item.properties.center;
            });

            let data = [];
            _data.map((item) => {
              let name = item.name
              let value = item.value || 0
              if (cityCenter[name]) {
                data.push({
                  name: name,
                  value: cityCenter[name].concat(value),
                });
              }
            });
            console.info(data)
            this.length = data.length
            this.init(name, data);
          }
        },
        immediate: true,
        deep: true
      }
    },
    methods: {
      init(name, data) {
        let top = 30;
        let zoom = 1.15
        let scale = 0.95
        this.options = {
          backgroundColor: "rgba(0,0,0,0)",
          tooltip: {
            show: true,
            trigger: 'item',
            textStyle: {
              fontSize: 16,
              lineHeight: 22,
            },
            formatter: function (params) {
              if (params.data) {
                return params.name + ":" + params.data["value"][2];
              } else {
                return params.name;
              }
            },
            backgroundColor: "rgba(0,0,0,.6)",
            borderColor: "rgba(147, 235, 248, .8)",
            textStyle: {
              color: "#FFF",
            },
            position: point => {
              // 固定在顶部
              return [point[0] + 5, point[1] - 20];
            },
          },
          legend: {
            show: false,
          },
          visualMap: {
            show: false,
            left: 0,
            bottom: 20,
            pieces: [
              { gte: 1000, label: "1000个以上" }, // 不指定 max,表示 max 为无限大(Infinity)。
              { gte: 600, lte: 999, label: "600-999个" },
              { gte: 200, lte: 599, label: "200-599个" },
              { gte: 50, lte: 199, label: "49-199个" },
              { gte: 10, lte: 49, label: "10-49个" },
              { lte: 9, label: "1-9个" }, // 不指定 min,表示 min 为无限大(-Infinity)。
            ],
            inRange: {
              color: "#0782b7",
            },
            /*inRange: {
              // 渐变颜色,从小到大
              color: [
                "#c3d7df",
                "#5cb3cc",
                "#8abcd1",
                "#66a9c9",
                "#2f90b9",
                "#1781b5",
              ],
            },*/
            textStyle: {
              color: "#fff",
            },
          },
          geo: {
            map: name,
            roam: false,
            selectedMode: false, //是否允许选中多个区域
            zoom: zoom,
            top: top,
            aspectScale: scale, //长宽比
            show: true,
          },
          series: [
            {
              type: "map",
              map: name,
              aspectScale: scale, //长宽比
              zoom: zoom,
              top: top,
              data: data, //数据
              selectedMode: false, //是否允许选中多个区域
              geoIndex: 1,
              //地图省份选中样式
              emphasis: {
                label: {
                  show: true,
                },
                itemStyle: {
                  areaColor: "#389BB7", // 背景色,默认是黄色
                  borderWidth: 1,
                },
              },
              //地图背景色
              itemStyle: {
                color: "#47C1BF",
                areaColor: 'rgba(19,54,162, .5)',
                borderColor: 'rgba(0,242,252,.3)',
                borderWidth: 1,
                shadowBlur: 7,
                shadowColor: '#47C1BF',
              },
            },
            {
              data: data || [],
              type: "effectScatter",
              coordinateSystem: "geo",
              symbolSize: function (val) {
                val = val[2] || 0
                if (val >= 5000) return 10;
                else if (val >= 1000) return 5;
                else if (val >= 800) return 4;
                else if (val >= 600) return 3;
                else if (val >= 400) return 2;
                else if (val >= 200) return 1;
                else if (val >= 1) return 0.5;
                else return 0;
              },
              legendHoverLink: true,
              showEffectOn: "render",
              rippleEffect: {
                // period: 4,
                scale: 6,
                color: "rgba(255,255,255, 0.6)",
                brushType: "fill",
              },
              //地图中心点显示样式
              label: {
                show: false,
                formatter: (params) => {
                  if (params.data) {
                    return params.name + ":" + params.data["value"][2];
                  } else {
                    return params.name;
                  }
                },
                fontSize: 11,
                offset: [0, 2],
                position: "bottom",
                textBorderColor: "#fff",
                textShadowColor: "#000",
                textShadowBlur: 10,
                textBorderWidth: 0,
                color: "#47C1BF",
              },
              // colorBy: "data",
              itemStyle: {
                color: "rgba(255,255,255,1)",
                borderColor: "rgba(2255,255,255,2)",
                borderWidth: 4,
                shadowColor: "#47C1BF",
                shadowBlur: 10,
              }
            }
          ]
        }
        // 重新选择区域
        this.handleMapRandomSelect();
      },
      // 开启定时器
      startInterval() {
        const _self = this;
        const time = 3000;
        if (this.intervalId !== null) {
          clearInterval(this.intervalId);
        }
        this.intervalId = setInterval(() => {
          _self.reSelectMapRandomArea();
        }, time);
      },
      // 重新随机选中地图区域
      reSelectMapRandomArea() {
        this.$nextTick(() => {
          try {
            let ref = this.$refs.map
            if (ref) {
              const map = ref.chart;
              let index = Math.floor(Math.random() * this.length);
              while (index === this.preSelectMapIndex || index >= this.length) {
                index = Math.floor(Math.random() * this.length);
              }
              map.dispatchAction({
                type: 'mapUnSelect',
                seriesIndex: 0,
                dataIndex: this.preSelectMapIndex,
              });
              map.dispatchAction({
                type: 'showTip',
                seriesIndex: 0,
                dataIndex: index,
              });
              map.dispatchAction({
                type: 'mapSelect',
                seriesIndex: 0,
                dataIndex: index,
              });
              this.preSelectMapIndex = index;
            }
          } catch (error) {
          }
        });
      },
      handleMapRandomSelect() {
        this.$nextTick(() => {
          try {
            let ref = this.$refs.map
            if (ref) {
              const map = ref.chart;
              const _self = this;
              setTimeout(() => {
                _self.reSelectMapRandomArea();
              }, 0);
              // 移入区域,清除定时器、取消之前选中并选中当前
              map.on('mouseover', function (params) {
                clearInterval(_self.intervalId);
                map.dispatchAction({
                  type: 'mapUnSelect',
                  seriesIndex: 0,
                  dataIndex: _self.preSelectMapIndex,
                });
                map.dispatchAction({
                  type: 'mapSelect',
                  seriesIndex: 0,
                  dataIndex: params.dataIndex,
                });
                _self.preSelectMapIndex = params.dataIndex;
              });
              // 移出区域重新随机选中地图区域,并开启定时器
              map.on('globalout', function () {
                _self.reSelectMapRandomArea();
                _self.startInterval();
              });
              this.startInterval();
            }
          } catch (error) {
          }
        });
      },
    }
  }
</script>

common/map.js 内容过长,节选展示

const mapJson={"type":"FeatureCollection","features":[{"type":"Feature","properties":{"adcode":820000,"name":"澳门","center":[113.54909,22.198951],"centroid":[113.566988,22.159307],"childrenNum":8,"level":"province","parent":{"adcode":100000},"subFeatureIndex":33,"acroutes":[100000]},"geometry":{"type":"MultiPolygon","coordinates":[[[[113.554425,22.107489],[113.6037,22.132438],[113.575983,22.194513],[113.558736,22.212244],[113.53841,22.209473],[113.534715,22.174009],[113.554425,22.142416],[113.554425,22.107489]]],[[[113.586453,22.201162],[113.575983,22.201162],[113.575983,22.194513],[113.586453,22.201162]]]]}}]}
export default {mapJson}

封装的echart组件echart/index.vue

<template>
  <div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>

<script>
import tdTheme from './theme.json' // 引入默认主题

export default {
  name: 'echart',
  props: {
    className: {
      type: String,
      default: 'chart'
    },
    id: {
      type: String,
      default: 'chart'
    },
    width: {
      type: String,
      default: '100%'
    },
    height: {
      type: String,
      default: '2.5rem'
    },
    options: {
      type: Object,
      default: ()=>({})
    }
  },
  data () {
    return {
      chart: null
    }
  },
  watch: {
    options: {
      handler (options) {
        // 设置true清空echart缓存
        this.chart.setOption(options, true)
      },
      deep: true
    }
  },
  mounted () {
    this.$echarts.registerTheme('tdTheme', tdTheme); // 覆盖默认主题
    this.initChart();
  },
  beforeDestroy () {
    this.chart.dispose()
    this.chart = null
  },
  methods: {
    initChart () {
      // 初始化echart
      this.chart = this.$echarts.init(this.$el, 'tdTheme')
      this.chart.setOption(this.options, true)
    }
  }
}
</script>

theme.json

{
  "color": [
    "#2d8cf0",
    "#19be6b",
    "#ff9900",
    "#E46CBB",
    "#9A66E4",
    "#ed3f14"
  ],
  "backgroundColor": "rgba(0,0,0,0)",
  "textStyle": {},
  "title": {
    "textStyle": {
      "color": "#516b91"
    },
    "subtextStyle": {
      "color": "#93b7e3"
    }
  },
  "line": {
    "itemStyle": {
      "normal": {
        "borderWidth": "2"
      }
    },
    "lineStyle": {
      "normal": {
        "width": "2"
      }
    },
    "symbolSize": "6",
    "symbol": "emptyCircle",
    "smooth": true
  },
  "radar": {
    "itemStyle": {
      "normal": {
        "borderWidth": "2"
      }
    },
    "lineStyle": {
      "normal": {
        "width": "2"
      }
    },
    "symbolSize": "6",
    "symbol": "emptyCircle",
    "smooth": true
  },
  "bar": {
    "itemStyle": {
      "normal": {
        "barBorderWidth": 0,
        "barBorderColor": "#ccc"
      },
      "emphasis": {
        "barBorderWidth": 0,
        "barBorderColor": "#ccc"
      }
    }
  },
  "pie": {
    "itemStyle": {
      "normal": {
        "borderWidth": 0,
        "borderColor": "#ccc"
      },
      "emphasis": {
        "borderWidth": 0,
        "borderColor": "#ccc"
      }
    }
  },
  "scatter": {
    "itemStyle": {
      "normal": {
        "borderWidth": 0,
        "borderColor": "#ccc"
      },
      "emphasis": {
        "borderWidth": 0,
        "borderColor": "#ccc"
      }
    }
  },
  "boxplot": {
    "itemStyle": {
      "normal": {
        "borderWidth": 0,
        "borderColor": "#ccc"
      },
      "emphasis": {
        "borderWidth": 0,
        "borderColor": "#ccc"
      }
    }
  },
  "parallel": {
    "itemStyle": {
      "normal": {
        "borderWidth": 0,
        "borderColor": "#ccc"
      },
      "emphasis": {
        "borderWidth": 0,
        "borderColor": "#ccc"
      }
    }
  },
  "sankey": {
    "itemStyle": {
      "normal": {
        "borderWidth": 0,
        "borderColor": "#ccc"
      },
      "emphasis": {
        "borderWidth": 0,
        "borderColor": "#ccc"
      }
    }
  },
  "funnel": {
    "itemStyle": {
      "normal": {
        "borderWidth": 0,
        "borderColor": "#ccc"
      },
      "emphasis": {
        "borderWidth": 0,
        "borderColor": "#ccc"
      }
    }
  },
  "gauge": {
    "itemStyle": {
      "normal": {
        "borderWidth": 0,
        "borderColor": "#ccc"
      },
      "emphasis": {
        "borderWidth": 0,
        "borderColor": "#ccc"
      }
    }
  },
  "candlestick": {
    "itemStyle": {
      "normal": {
        "color": "#edafda",
        "color0": "transparent",
        "borderColor": "#d680bc",
        "borderColor0": "#8fd3e8",
        "borderWidth": "2"
      }
    }
  },
  "graph": {
    "itemStyle": {
      "normal": {
        "borderWidth": 0,
        "borderColor": "#ccc"
      }
    },
    "lineStyle": {
      "normal": {
        "width": 1,
        "color": "#aaa"
      }
    },
    "symbolSize": "6",
    "symbol": "emptyCircle",
    "smooth": true,
    "color": [
      "#2d8cf0",
      "#19be6b",
      "#f5ae4a",
      "#9189d5",
      "#56cae2",
      "#cbb0e3"
    ],
    "label": {
      "normal": {
        "textStyle": {
          "color": "#eee"
        }
      }
    }
  },
  "map": {
    "itemStyle": {
      "normal": {
        "areaColor": "#f3f3f3",
        "borderColor": "#516b91",
        "borderWidth": 0.5
      },
      "emphasis": {
        "areaColor": "rgba(165,231,240,1)",
        "borderColor": "#516b91",
        "borderWidth": 1
      }
    },
    "label": {
      "normal": {
        "textStyle": {
          "color": "#000"
        }
      },
      "emphasis": {
        "textStyle": {
          "color": "rgb(81,107,145)"
        }
      }
    }
  },
  "geo": {
    "itemStyle": {
      "normal": {
        "areaColor": "#f3f3f3",
        "borderColor": "#516b91",
        "borderWidth": 0.5
      },
      "emphasis": {
        "areaColor": "rgba(165,231,240,1)",
        "borderColor": "#516b91",
        "borderWidth": 1
      }
    },
    "label": {
      "normal": {
        "textStyle": {
          "color": "#000"
        }
      },
      "emphasis": {
        "textStyle": {
          "color": "rgb(81,107,145)"
        }
      }
    }
  },
  "categoryAxis": {
    "axisLine": {
      "show": true,
      "lineStyle": {
        "color": "#cccccc"
      }
    },
    "axisTick": {
      "show": false,
      "lineStyle": {
        "color": "#333"
      }
    },
    "axisLabel": {
      "show": true,
      "textStyle": {
        "color": "#fff"
      }
    },
    "splitLine": {
      "show": false,
      "lineStyle": {
        "color": [
          "#eeeeee"
        ]
      }
    },
    "splitArea": {
      "show": false,
      "areaStyle": {
        "color": [
          "rgba(250,250,250,0.05)",
          "rgba(200,200,200,0.02)"
        ]
      }
    }
  },
  "valueAxis": {
    "axisLine": {
      "show": true,
      "lineStyle": {
        "color": "#cccccc"
      }
    },
    "axisTick": {
      "show": false,
      "lineStyle": {
        "color": "#333"
      }
    },
    "axisLabel": {
      "show": true,
      "textStyle": {
        "color": "#fff"
      }
    },
    "splitLine": {
      "show": false,
      "lineStyle": {
        "color": [
          "#eeeeee"
        ]
      }
    },
    "splitArea": {
      "show": false,
      "areaStyle": {
        "color": [
          "rgba(250,250,250,0.05)",
          "rgba(200,200,200,0.02)"
        ]
      }
    }
  },
  "logAxis": {
    "axisLine": {
      "show": true,
      "lineStyle": {
        "color": "#cccccc"
      }
    },
    "axisTick": {
      "show": false,
      "lineStyle": {
        "color": "#333"
      }
    },
    "axisLabel": {
      "show": true,
      "textStyle": {
        "color": "#999999"
      }
    },
    "splitLine": {
      "show": true,
      "lineStyle": {
        "color": [
          "#eeeeee"
        ]
      }
    },
    "splitArea": {
      "show": false,
      "areaStyle": {
        "color": [
          "rgba(250,250,250,0.05)",
          "rgba(200,200,200,0.02)"
        ]
      }
    }
  },
  "timeAxis": {
    "axisLine": {
      "show": true,
      "lineStyle": {
        "color": "#cccccc"
      }
    },
    "axisTick": {
      "show": false,
      "lineStyle": {
        "color": "#333"
      }
    },
    "axisLabel": {
      "show": true,
      "textStyle": {
        "color": "#999999"
      }
    },
    "splitLine": {
      "show": true,
      "lineStyle": {
        "color": [
          "#eeeeee"
        ]
      }
    },
    "splitArea": {
      "show": false,
      "areaStyle": {
        "color": [
          "rgba(250,250,250,0.05)",
          "rgba(200,200,200,0.02)"
        ]
      }
    }
  },
  "toolbox": {
    "iconStyle": {
      "normal": {
        "borderColor": "#999"
      },
      "emphasis": {
        "borderColor": "#666"
      }
    }
  },
  "legend": {
    "textStyle": {
      "color": "#fff"
    }
  },
  "tooltip": {
    "axisPointer": {
      "lineStyle": {
        "color": "#ccc",
        "width": 1
      },
      "crossStyle": {
        "color": "#ccc",
        "width": 1
      }
    }
  },
  "timeline": {
    "lineStyle": {
      "color": "#8fd3e8",
      "width": 1
    },
    "itemStyle": {
      "normal": {
        "color": "#8fd3e8",
        "borderWidth": 1
      },
      "emphasis": {
        "color": "#8fd3e8"
      }
    },
    "controlStyle": {
      "normal": {
        "color": "#8fd3e8",
        "borderColor": "#8fd3e8",
        "borderWidth": 0.5
      },
      "emphasis": {
        "color": "#8fd3e8",
        "borderColor": "#8fd3e8",
        "borderWidth": 0.5
      }
    },
    "checkpointStyle": {
      "color": "#8fd3e8",
      "borderColor": "rgba(138,124,168,0.37)"
    },
    "label": {
      "normal": {
        "textStyle": {
          "color": "#8fd3e8"
        }
      },
      "emphasis": {
        "textStyle": {
          "color": "#8fd3e8"
        }
      }
    }
  },
  "visualMap": {
    "color": [
      "#516b91",
      "#59c4e6",
      "#a5e7f0"
    ]
  },
  "dataZoom": {
    "backgroundColor": "rgba(0,0,0,0)",
    "dataBackgroundColor": "rgba(255,255,255,0.3)",
    "fillerColor": "rgba(167,183,204,0.4)",
    "handleColor": "#a7b7cc",
    "handleSize": "100%",
    "textStyle": {
      "color": "#333"
    }
  },
  "markPoint": {
    "label": {
      "normal": {
        "textStyle": {
          "color": "#eee"
        }
      },
      "emphasis": {
        "textStyle": {
          "color": "#eee"
        }
      }
    }
  }
}

main.js

// 按需引入vue-awesome图标
import Icon from 'vue-awesome/components/Icon';
import 'vue-awesome/icons/map.js';
import dataV from '@jiaminghi/data-view';
import Echart from './common/echart/index.vue'
// 全局注册
Vue.component('icon', Icon);
Vue.component("Echart", Echart)
Vue.use(dataV);

//引入echart
//4.x 引用方式
//import echarts from 'echarts';
//5.x 引用方式为按需引用
//希望使用5.x版本的话,需要在package.json中更新版本号,并切换引用方式
import * as echarts from 'echarts'  //本例使用的是^5.4.0版本
Vue.prototype.$echarts = echarts
转载请注明出处或者链接地址:https://www.qianduange.cn//article/15402.html
标签
评论
发布的文章

HTML5 地理定位

2024-08-20 09:08:58

HTML5 的真相(一)

2024-08-20 09:08:31

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!