echarts中国地图自定义大区(支持以城市划分大区)

5,251 阅读5分钟

echarts中国地图自定义大区(支持以城市划分大区)

自定义大区的效果

xian.png

[项目地址]gitee.com/cgshuai/chi…)

如何实现自定义大区呢

经过查找api发现: echarts.registerMap("china", mapJSON); // 注册地图 只需要得到一份自定义大区的json数据:mapJSON 就可以了; 如何得到呢

//数据
var areaParams = {
  area: [
    {
      araeName: "成都服务区",
      children: ["四川省", "重庆市", "西藏自治区"],
      center: [104.065735, 30.659462],
    },
    {
      center: [113.280637, 23.125178],
      araeName: "广州服务区",
      children: [
        "广西壮族自治区",
        "广东省",
        "海南省",
        ["福州市", "龙岩市", "莆田市", "泉州市", "三明市", "厦门市", "漳州市"], //福建
      ],
    },
    //...还有更多服务区数据请查看项目连接

  ]
};
var myChart = echarts.init(document.getElementById("container"));
// var mapJSON = aliChina;
function draw(mapJSON) {
  echarts.registerMap("china", mapJSON); // 注册地图
 

  myChart.clear();

  var option = {
    grid: {
      left: "2%",
      right: "2%",
      bottom: "5%",
      top: "5%",
      containLabel: true,
    },

    tooltip: {
      enterable: true,
      formatter: function (params) {
        var value = params.value;
        let result = params.name + ": " + value[2]; // 最后一定要是 个字符串
        return result;
      },
    }, // 配置提示框,提示框默认显示value中的第二段

    geo: {
      map: "china", // 表示中国地图
      roam: true, // 是否开启鼠标缩放和平移漫游
      zoom: 1.2, // 当前视角的缩放比例(地图的放大比例)
      scaleLimit: {
        min: 0.5,
        max: 4,
      },

      itemStyle: {
        normal: {
          borderWidth: 1, //区域边框宽度
          borderColor: "#059CC0 ", //区域边框颜色
          "rgb(219,230,248)", //区域颜色
        },

        emphasis: {
          borderWidth: 1,
          borderColor: "#4b0082",
          areaColor: "#ece39e",
        },
      },
    },

    series: [
      {
        type: "effectScatter", //  指明图表类型:带涟漪效果的散点图
        coordinateSystem: "geo", //  指明绘制在geo坐标系上
        Symbol: "rect",
        itemStyle: {
          // 配置每个数据点的样式
          color: function (params) {
            var color = "";
            var value = params.value;
            color = "#E6A63E";
            return color;
          },
        },

        symbolSize: function (val) {
          return 8;
        },
        zlevel: 2,
        cursor: "pointer",
        hoverAnimation: true,
        // data: seriesData,
      },
    ],
  };

  myChart.setOption(option, true);
}

// aliChinaCity
// aliChina
// areaParams :{
//  area:[]
// }

function mergeProvinces(area, chinaJson, chinaCityJson) {
  // type Polygon  type: "MultiPolygon",
  var features = [];
  var chinaFeatures = chinaJson.features;
  var chinaCityFeatures = chinaCityJson.features;
  area.forEach((areaItem, i) => {
    let fetureItem = {
      type: "Feature",
      properties: { name: areaItem.araeName, center: areaItem.center },
      geometry: {
        type: "MultiPolygon",
        coordinates: [],
      },
    };
    let coordinates = [];

    areaItem.children &&
      areaItem.children.forEach(childrenItem => {
        // childrenItem:四川省 / [];
        let obj = {};
        if (typeof childrenItem === "string") {
          // 去全国找    properties: { adcode: 110000, name: "北京市",
          obj = chinaFeatures.find(item => item.properties.name === childrenItem);
          obj.properties.araeName = areaItem.araeName;
          if (!obj) {
            console.log("🚀 ~ file: chinamapAli.js ~ line 157 ~ areaItem.children.forEach---->没找到 ~ obj", childrenItem);
          } else {
            if (obj.geometry.type === "MultiPolygon") {
              coordinates.push(obj.geometry.coordinates.flat(1));
            } else if (obj.geometry.type === "Polygon") {
              coordinates.push(obj.geometry.coordinates);
            }
          }
        } else if (typeof childrenItem === "object") {
          childrenItem.forEach(cityName => {
            obj = chinaCityFeatures.find(item => item.properties.name === cityName);
            if (!obj) {
              /* *
                * 丰城市/高安市->宜春市
                 莱芜市->撤销 归济南
                 巢湖市->合肥
                 青州市->山东省潍坊市
            */
            } else {
              // console.log(obj);
              if (obj.geometry.type === "MultiPolygon") {
                coordinates.push(obj.geometry.coordinates.flat(1));
              } else if (obj.geometry.type === "Polygon") {
                coordinates.push(obj.geometry.coordinates);
              }
            }
          });
          // console.log(childrenItem, "  // 去全国城市找");
        }
      });
    fetureItem.geometry.coordinates = coordinates;
>     features.push(fetureItem);
  });
  // adcode: "100000_JD"
  // properties
  let item = chinaFeatures.find(item => item.properties.adcode === "100000_JD");
  features.push(item); //缺失的一部分
  mapJSON = {
    type: "FeatureCollection",
    features: features,
  };
  draw(mapJSON);
  chinaFeatures.forEach(item => {
    // properties: { name: areaItem.araeName, center: areaItem.center },
    if (!item.properties.araeName) {
      console.log("araeName 不存在----->", item);
    }
  });
  // console.log("🚀 ~ file: chinamapAli.js ~ line 130 ~ mergeProvinces ~ area, chinaJson, chinaCityJson", area, chinaJson, chinaCityJson, features);
}
mergeProvinces(areaParams.area, aliChina, aliChinaCity);

aliChina, aliChinaCity 2个json 数据如何来的的?

aliChina是阿里云可视化平台datav.aliyun.com/portal/scho…下载的中国地图geoJson; aliChinaCity也是该平台下载的34个省市自治区的gheoJson 文件通过node 合并生成的一份 全国城市图;

说到这里,不知道有人会不会想,干嘛要自己去生成一份aliChinaCity啊,因为我没找到啊;那为什么不用 echarts4的map 的china.json;(如下图的:npm i ehcarts@4.9 -S node_modules 就可以找到) map.png

我第一版用的了charts 的map json;当然关于echarts 中国地图 钓鱼岛 缺失等问题 我肯定都处理好了;做好后 也是如下图注意事项1.的图片那样,城市 碎片化,很丑 ,那要怎么处理呢?

合并边界线 : ehcarts的 china.json mapshaper竟然不支持;它支持阿里云的geoJson 数据;所有我才用了现在的阿里云china数据,生成一份合并边界线后的chianJson

合并边界线第一版 我合并了大区的边界线,把省份边界线也合并了,只能看到区域的,省份在哪,你只能去猜了,这一版当然不合格

合并边界线第二版 生成 1份大区 省份 povince.json 文件 ,1份 大区 城市 city.json文件 ; 然后 把城市的那份 json 文件 通过 mapshaper 合并城市边界线 city2.json; 在合并 povince.json 和 city2.json;得到最终版的china.json

注意事项:

1. 以城市划分大区,会因为城市边界线给人一种 地图碎片化的效果, 比如: 下图的河南,福建,江西 等 省份 因为 业务需求 被以城市划分 到不同的 大区中;

suipian (2).png 2. 虽然合并后效果出来了,但 客户仍不满意,要的效果是:静态的的只有省份分界线, 悬浮高亮时才有 大区背景色 高亮,城市大区边界线才可以出来;

思路:这个效果需要1套自定义大区的数据,1套阿里云可视化平台china.json;所有 需要2个地图; 2个div 定位在一起position:absolute; 底图 使用里云可视化平台china.json,拥有背景色; 上面的地图 使用自定义大区的那层,背景色 使用 rgba(255,255,255,0.01); 之前使用了 transparent 但发现悬浮高亮时会有一闪而逝阴影的bug,才改为rgba(255,255,255,0.01); 还有因为使用了2个地图重叠,所以 缩放拖拽功能 也关闭了(roam: false);不然缩放时步调不一致那就尴尬了

//上图的
    itemStyle: {
            normal: {
            borderWidth: 0, //区域边框宽度 上图背景色透明,区域边框设置为0;这样显示的就是下图的省界了
             areaColor: 'rgba(255,255,255,0.01)'  //"transparent ", 
          },
          emphasis: {
            borderWidth: 0.5,
            borderColor: "#4b0082",
            areaColor: "#ece39e",
          },
        },

微信截图_20220111134632.png

微信图片编辑_20220111134742.jpg

3. 当客户的自定义大区数据调整 既areaParams调整 (重新分区,比如把青海省 调整到新疆 乌鲁木齐服务区),需要重新执行 node ,生成新的 json文件,重新合并 分区..... 因为要合并边界线所以我没有什么好的方法,如果大家有 好的方法 可以在评论下面提出,大家一起完善;

欢迎大家指出文章中的不足和bug,让我们大家一起共同进步