echart implements map exploration and displays scatter plots

Introduction: Realize provincial level (Henan as an example) exploration and display scattered points while the data remains unchanged.

Completed picture:

1. Prepare map geoJSON, DataV.GeoAtlas geographic gadget series

Create a tool function: introduce all the files in the directory, pass in the place name and return the geoJson of the place (dynamic references are used here)

// util.js
const modulesFiles = require.context('../../static/map/henanCitys', true, /\.json$/)
const lib = {}
modulesFiles.keys().forEach(item => {
  let str = item.replace(/^\.\/(.*)\.\w + $/, '$1')
  lib[str] = require(`../../static/map/henanCitys/${str}.json`)
})

export function getMap(mapName) {
    const cityJson = lib[mapName]
    if(cityJson){
        return cityJson
    }
}
2, initialize map component
<template>
  <div id="dpmap" />
</template>
import geoJson from "static/map/henan.json";
export default {
  props: {
    value: {
      type: Array,
      default: [],
    },
    resizeChange: "",
  },
  data() {
    return {
      chart: null,
      provinceOption: null,
      cityOption: null,
      mapArr: [],//scatter data
    };
  },
  watch: {
    value: {
      deep: true,
      handler(val) {
          this.setProvinceOptions(val);
      },
    },
    resizeChange: {
      deep: true,
      handler(val) {
        this.chart.resize();
      },
    },
  },
  mounted() {
    //Register map
    echarts.registerMap("henan", geoJson);
    this.chart = echarts.init(document.getElementById("dpmap"));
  },
  beforeDestroy() {
    if (!this.chart) {
      return;
    }
    this.chart.dispose();
    this.chart = null;
  },
3. Render provincial maps and scatter points (define click events to prepare for drilling operations)
setProvinceOptions(val) {
      
      this.mapArr=val.map(item=>{
        return {
          name: item.orgName,
          value: [item.longitude||112.540918, item.latitude||32.999082, item.consNum||0],
        }
      })
      this.provinceOption = {
        tooltip: this.publicOption.tooltip,
        geo: [
          {
            map: "henan",
            aspectScale: 1,
            top: 20,
            bottom: 20,
            zlevel: 0,
            label: this.publicOption.geo.label,
            itemStyle: this.publicOption.geo.itemStyle,
          },
          
        ],
        series: [
          {
            type: "scatter",
            animationDurationUpdate: 0,
            zlevel: 2,
            coordinateSystem: "geo",
            data: this.mapArr,
            symbolSize:function(value){
              return value[2]<10?5:value[2]<20?10:20
            },
            label: {
              show: false,
            },
            itemStyle: {
              color: "#ffaa67",
            },
          },
          {
            map: "henan",
            type: "map",
            zlevel: -1,
            left: -5,
            right: 5,
            top: 30,
            bottom: 10,
            silent: true,
            itemStyle: this.publicOption.series.itemStyle,
          },
        ],
      }

      this.chart.setOption(this.provinceOption);

      this.chart.on('click', (params) => {
        this.setCityOptions(params)

      })
    },
4, Rendering next-level maps and scatter points
setCityOptions(params) {
      // Return if clicked
      if(params.componentType == "graphic") {
        return this.chart.setOption(this.provinceOption, true);
      }
      let cityJson = getMap(params.name)

      /* Determine whether the data is in the map */
      //Load the polygons of the map
      let polygons = [];
      cityJson.features.forEach(item => {
        polygons.push(turf.polygon(...item.geometry.coordinates))
      })
      let mapArr = this.mapArr.filter(item => {
        // Determine whether the point is within the polygon
        return polygons.some(item1 => {
          return turf.booleanPointInPolygon(turf.point([item.value[0],item.value[1]]), item1)
        })
        
      })
      
      //Click on the city
      if(cityJson){
        echarts.registerMap(params.name, cityJson);
        this.cityOption = {
          title: {
            text: 'Henan Province-' + params.name,
            top: "5%",
            left: "5%",
          },
          tooltip: this.publicOption.tooltip,
          geo: [
            {
              map: params.name,
              top: 50,
              left: 50,
              bottom: 30,
              right: 50,
              zlevel: 0,
              clip: true,
              label: this.publicOption.geo.label,
              itemStyle: this.publicOption.geo.itemStyle,
            },
          ],
          series: [
            {
              name: params.name,
              type: "map",
              map: params.name,
              data: cityJson,
              clip: true,
              zlevel: -1,
              top: 60,
              bottom: 20,
              left: 60,
              right: 40,
              silent: true,
              itemStyle: this.publicOption.series.itemStyle,
            },
            {
              type: "scatter",
              animationDurationUpdate: 0,
              zlevel: 2,
              coordinateSystem: "geo",
              data: mapArr,
              symbolSize:function(value){
                return value[2]<10?5:value[2]<20?10:20
              },
              clip: true,
              label: {
                show: false,
              },
              itemStyle: {
                color: "#ffaa67",
              },
            },
          ],
          graphic: {
            type: "text",
            top: "5%",
            right: "5%",
            zlevel: 9,
            style: {
              text: "←Return",
              fill: '#fff',
              fontSize: "20px"
            }
          },
        }
        this.chart.setOption(this.cityOption, true)
      }
    }

Different from the provincial level, you need a return button (graphic definition), create a corresponding return event, and then use setOption to re-render the page (true means not to merge with the original configuration).

Call the tool function getMap() to register the map.

At this time, you will find a difficult point to deal with. If there is only a set of original data this.mapArr and no interface is adjusted, the scatter plot will exceed the map. We need to remove the points that exceed the map.

How to remove? Introduce the truf.js library to help us calculate.

Remember geoJSON at the beginning? Its data format is like this

We use polygon to convert the coordinate points into polygons, then use booleanPointInPolygon to determine whether a point is within its polygon, and traverse all polygons to filter the data. Then perform configuration rendering. At this point, the function is completed.