最近项目中需要集成echarts中的map3D地图,开发过程中遇到过不少问题,这里mark下,有遇到相应问题的伙伴欢迎一起交流

相关源码下载
1、世界地图.js,中国地图.js,中国各省份地图.js
2、echarts基础报表js源文件(echarts.min.js)
3、3D地图所需的js文件(echarts-gl.min.js)
生成geojson网址
vue项目直接安装相应插件,将省市区引入即可。
echarts:npm install vue-echarts -save
echarts-gl:npm install echarts-gl -save

vue-echarts和echarts的区别:vue-echarts是封装后的vue插件, 基于 ECharts v4.0.1+ 开发,依赖 Vue.js v2.2.6+,功能一样的只是把它封装成vue插件 这样更方便以vue的方式去使用它。

效果图
浙江省3D地图
杭州市市级地图

echarts引入自定义地图数据分两种形式,引入js和geojson方式,下面简单介绍在vue项目中引入方式
1、通过js方式引入,这里已浙江省为例
我这边是将js文件放置在assets目录下,直接在页面引入

import "../../assets/js/zhejiang.js";

2、通过geojson文件引入,这边对应的是浙江省对应的下级市数据

import hangzhou from "../../assets/js/city/hangzhou.json";
import huzhou from "../../assets/js/city/huzhou.json";
import jiaxing from "../../assets/js/city/jiaxing.json";
import shaoxing from "../../assets/js/city/shaoxing.json";
import quzhou from "../../assets/js/city/quzhou.json";
import jinhua from "../../assets/js/city/jinhua.json";
import taizhou from "../../assets/js/city/taizhou.json";
import zhoushan from "../../assets/js/city/zhoushan.json";
import ningbo from "../../assets/js/city/ningbo.json";
import wenzhou from "../../assets/js/city/wenzhou.json";
import lishui from "../../assets/js/city/lishui.json";

geojson引入时需注册地图echarts.registerMap(‘杭州‘, hangzhou);

完整代码如下

<div id="map" ref="myEchart"></div>

data() {
    return {
      city: {
        浙江: "zhejiang",
        杭州市: hangzhou,
        湖州市: huzhou,
        嘉兴市: jiaxing,
        绍兴市: shaoxing,
        衢州市: quzhou,
        金华市: jinhua,
        台州市: taizhou,
        舟山市: zhoushan,
        宁波市: ningbo,
        温州市: wenzhou,
        丽水市:lishui
      },
      isProvince: true,
    };
  }
  //option定义
let option = {
        tooltip: {
          show: true,
          formatter: (params) => {
            return `<div style="position:absolute;left:0;top:0;width:8px;height:8px;background-color:#FD9A5A;"></div>
            <div class='tips' style="padding:0 12px;">
                <h1 style='font-size:16px;'>${params.name}</h1>
                <p style="font-size:14px;"><span style="opacity:0.75">办理人数:</span>22人</p>
                <p style="font-size:14px;"><span style="opacity:0.75">待办人数:</span>22人</p>
                <p style="font-size:14px;"><span style="opacity:0.75">办结人数:</span>22人</p>
            </div>`;
          },
          borderColor: "#998484",
          borderWidth: 1,
          padding: [0, 0],
          backgroundColor: "#1B212B",
          borderRadius: 0,
          // textStyle: { color: "blue" },
        },
        visualMap: {
          show: false,
          min: min, //指定 visualMapContinuous 组件的允许的最小值。
          max: max, //指定 visualMapContinuous 组件的允许的最大值
          inRange: {
            color: ["#008FFF"],
          },
          calculable: true, //是否显示拖拽用的手柄(手柄能拖拽调整选中范围)。
        },
        series: {
          name: "浙江",
          type: "map3D",
          map: name, //地图类型。echarts-gl 中使用的地图类型同 geo 组件相同
          regionHeight: 2, //模型的高度
          boxWidth: 70, //三维地图在三维场景中的宽度
          //boxHeight:50,
          boxDepth: 60, //三维地图在三维场景中的深度
          top: "-10%",
          //left:'10%',

          label: {
            show: true, //是否显示标签。
            position: ["50%", "50%"],
            formatter: (params) => {
              params.name;
            },
            textStyle: {
              color: "rgba(255,255,255,0.65)", //地图初始化区域字体颜色
              fontSize: 16,
              opacity: 1,
              backgroundColor: "#1B212B ",
              borderColor: "#998484",
              borderWidth: 1,
              position: "insideTop",
              padding: [6, 8],
              borderRadius: 0,
              distanca: 20,
            },

            emphasis: {
              //对应的鼠标悬浮效果
              show: true,
              // textStyle: { color: "blue" }
            },
          },
          itemStyle: {
            normal: {
              //静态模式下显示的默认样式
              borderWidth: 1.6,
              borderColor: "#95FFFF",
              color: "#0090FF",
            }, //阴影效果
            emphasis: {
              鼠标移上去的样式
              borderWidth: 1.6,
              borderColor: "#95FFFF",
              color: "#0058B8",
              textStyle: {
                // color:'blue'
              },
            },
          },

          viewControl: {
            //用于鼠标的旋转,缩放等视角控制。
            autoRotate: false, //是否开启视角绕物体的自动旋转查看
            distance: 70, //默认视角距离主体的距离,对于 globe 来说是距离地球表面的距离,对于 grid3D 和 geo3D 等其它组件来说是距离中心原点的距离。在 projection 为'perspective'的时候有效。
          },
        },
      };
Echarts = echarts.init(this.$refs.myEchart);
Echarts.setOption(option);
window.onresize = Echarts.resize();

到这里省地图默认就出来了,下面来说下如何点击省地图板块跳到对应市级地图,也就是我们所说的下穿,首先需要在省级地图点击事件里执行

 Echarts.on("click", (e) => {
  if(this.isProvince) this.renderMap(e.name);
});

这边的renderMap是我这边封装的,隐藏省级地图,展示市级地图

renderMap(name) {
  console.log(name, this.city[name]);
  if (name != "浙江省" && name) {
    this.isProvince = false;
    echarts.registerMap(name, this.city[name]); //获取对应的json数据,最主要的
    Echarts.clear();	//清除echarts
    this.map(name);
    this.$emit("changeMap", name);		//这边封装成组件,所以做了处理
  } else if(name=='浙江省'){
      this.isProvince = true;
        Echarts.clear();	//清除echarts
        this.map();
        this.$emit("changeMap", name);	//这边封装成组件,所以做了处理
  }else {
    this.isProvince = true;
    Echarts.clear();	//清除echarts
    this.map();
  }
 
},

这边将页面封装成了组件,父级有选择省和市的下拉框,这边调用组件时将省或市的名称传入即可

echarts.registerMap(name, this.city[name]); 

city是我在上面定义的对应市名称和json数据,选择市级时调用对应的jjson数据,完整代码如下:

<template>
  <div>
    <div class="returnBtn" v-show="!isProvince" @click='renderMap("浙江省")'>返回</div>
    <div id="map" ref="myEchart"></div>
  </div>
</template>

<script>
import echarts from "echarts/lib/echarts";
import "echarts-gl";
import "../../assets/js/zhejiang.js";
import hangzhou from "../../assets/js/city/hangzhou.json";
import huzhou from "../../assets/js/city/huzhou.json";
import jiaxing from "../../assets/js/city/jiaxing.json";
import shaoxing from "../../assets/js/city/shaoxing.json";
import quzhou from "../../assets/js/city/quzhou.json";
import jinhua from "../../assets/js/city/jinhua.json";
import taizhou from "../../assets/js/city/taizhou.json";
import zhoushan from "../../assets/js/city/zhoushan.json";
import ningbo from "../../assets/js/city/ningbo.json";
import wenzhou from "../../assets/js/city/wenzhou.json";
import lishui from "../../assets/js/city/lishui.json";
let Echarts;
export default {
  props: {
    cityName: {
      type: String,
      default: "浙江",
    },
  },
  data() {
    return {
      city: {
        浙江: "zhejiang",
        杭州市: hangzhou,
        湖州市: huzhou,
        嘉兴市: jiaxing,
        绍兴市: shaoxing,
        衢州市: quzhou,
        金华市: jinhua,
        台州市: taizhou,
        舟山市: zhoushan,
        宁波市: ningbo,
        温州市: wenzhou,
        丽水市:lishui
      },
      isProvince: true,
    };
  },
  mounted() {
    this.map();
  },
  methods: {
    map(name = "浙江") {
      var min = 0,
        max = 300;
      let option = {
        tooltip: {
          show: true,
          formatter: (params) => {
            return `<div style="position:absolute;left:0;top:0;width:8px;height:8px;background-color:#FD9A5A;"></div>
            <div class='tips' style="padding:0 12px;">
                <h1 style='font-size:16px;'>${params.name}</h1>
                <p style="font-size:14px;"><span style="opacity:0.75">办理人数:</span>22人</p>
                <p style="font-size:14px;"><span style="opacity:0.75">待办人数:</span>22人</p>
                <p style="font-size:14px;"><span style="opacity:0.75">办结人数:</span>22人</p>
            </div>`;
          },
          borderColor: "#998484",
          borderWidth: 1,
          padding: [0, 0],
          backgroundColor: "#1B212B",
          borderRadius: 0,
          // textStyle: { color: "blue" },
        },
        visualMap: {
          show: false,
          min: min, //指定 visualMapContinuous 组件的允许的最小值。
          max: max, //指定 visualMapContinuous 组件的允许的最大值
          inRange: {
            color: ["#008FFF"],
          },
          calculable: true, //是否显示拖拽用的手柄(手柄能拖拽调整选中范围)。
        },
        series: {
          name: "浙江",
          type: "map3D",
          map: name, //地图类型。echarts-gl 中使用的地图类型同 geo 组件相同
          regionHeight: 2, //模型的高度
          boxWidth: 70, //三维地图在三维场景中的宽度
          //boxHeight:50,
          boxDepth: 60, //三维地图在三维场景中的深度
          top: "-10%",
          //left:'10%',

          label: {
            show: true, //是否显示标签。
            position: ["50%", "50%"],
            formatter: (params) => {
              params.name;
            },
            textStyle: {
              color: "rgba(255,255,255,0.65)", //地图初始化区域字体颜色
              fontSize: 16,
              opacity: 1,
              backgroundColor: "#1B212B ",
              borderColor: "#998484",
              borderWidth: 1,
              position: "insideTop",
              padding: [6, 8],
              borderRadius: 0,
              distanca: 20,
            },

            emphasis: {
              //对应的鼠标悬浮效果
              show: true,
              // textStyle: { color: "blue" }
            },
          },
          itemStyle: {
            normal: {
              //静态模式下显示的默认样式
              borderWidth: 1.6,
              borderColor: "#95FFFF",
              color: "#0090FF",
            }, //阴影效果
            emphasis: {
              鼠标移上去的样式
              borderWidth: 1.6,
              borderColor: "#95FFFF",
              color: "#0058B8",
              textStyle: {
                // color:'blue'
              },
            },
          },

          viewControl: {
            //用于鼠标的旋转,缩放等视角控制。
            autoRotate: false, //是否开启视角绕物体的自动旋转查看
            distance: 70, //默认视角距离主体的距离,对于 globe 来说是距离地球表面的距离,对于 grid3D 和 geo3D 等其它组件来说是距离中心原点的距离。在 projection 为'perspective'的时候有效。
          },
        },
      };
      Echarts = echarts.init(this.$refs.myEchart);
      Echarts.setOption(option);
      window.onresize = Echarts.resize();
      Echarts.on("click", (e) => {
        if (this.isProvince) this.renderMap(e.name);
      });
      // tooltip定时移动
      // var counts = 0;
      // if (timmerOneAnim) {
      //   clearInterval(timmerOneAnim);
      // }
      // let timmerOneAnim = setInterval(() => {
      //   Echarts.dispatchAction({
      //     type: "showTip",
      //     seriesIndex: 0,
      //     dataIndex: counts % city.length,
      //   });
      //   counts++;
      // }, 3000);
    },
    renderMap(name) {
      console.log(name, this.city[name]);
      if (name != "浙江省" && name) {
        this.isProvince = false;
        echarts.registerMap(name, this.city[name]); //获取对应的json数据,最主要的
        Echarts.clear();
        this.map(name);
        this.$emit("changeMap", name);
      } else if(name=='浙江省'){
          this.isProvince = true;
            Echarts.clear();
            this.map();
            this.$emit("changeMap", name);
      }else {
        this.isProvince = true;
        Echarts.clear();
        this.map();
      }
     
    },
  },
};
</script>

<style scoped lang='scss'>
@keyframes shake {
  0% {
    transform: scale(0);
    transform: rotate3d(1, 1, 1, 360deg);
    opacity: 0;
  }
  100% {
    transform: scale(1);
    transform: rotate3d(1, 1, 1, 0deg);
    opacity: 1;
  }
}
@-webkit-keyframes shake {
  0% {
    transform: scale(0);
    transform: rotate3d(1, 1, 1, 360deg);
    opacity: 0;
  }
  100% {
    transform: scale(1);
    transform: rotate3d(1, 1, 1, 0deg);
    opacity: 1;
  }
}
.returnBtn{
    font-size: 14px;
    color: rgba(255,255,255,0.8);
    margin-top: 20px;
    cursor: pointer;
}
#map {
  width: 620px;
  height: 465px;
  margin: 0 auto;
  animation: shake; /*动画名称*/
  animation-timing-function: linear;
  animation-duration: 2; /*动画持续时间*/
  -webkit-animation: shake 3s; /*针对webkit内核*/
}
</style>

页面调用如下

<mapComponents  @changeMap='changeMap' ref='mapComponents'></mapComponents>

import mapComponents from "./components/map.vue";

components: {mapComponents },

//调用
this.$refs.mapComponents.renderMap(this.city[e]);

效果如下
在这里插入图片描述
这边简单mark下,有些点没有详细的介绍,关于option设置就没有做说明了

Logo

前往低代码交流专区

更多推荐