LeafletJS simple use 1 - map point L.marker(), clear punctuation layerGroup.clearLayers() 【SuperMap iClient for Leaflet】Use of supermap

1. Business requirements

  1. Display the map, and display the corresponding icon at the specified latitude and longitude, click the icon to display detailed information
  2. There is a search function, when searching, punctuate on the map according to the searched data

2. Reference documents

The document provided by the map developer (the API in this document is the API used by the map manufacturer based on LeafletJS packaged by their gis hypermap _ In the end, this document should be used on the intranet to develop similar documents that can only be used on the intranet_ Intranet cannot access the Internet address)

  1. Development Platform https://iclient.supermap.io/10.2.0/web/index.html
  2. Map service https://iserver.supermap.io/iserver/services/map-world/rest/maps/World
  3. An example of an address that can display tiles: https://iserver.supermap.io/iserver/services/map-china400/rest/maps/China/tileImage.png?scale=2.1634093716513966e-7&x=103&y=50

LeafJS Reference Documentation

  1. English official website: https://leafletjs.com/
  2. Chinese reference: https://www.imangodoc.com/19243.html

3. Implementation ideas

  1. Implemented in the vue project, first download the dependency
    npm install @supermap/iclient-leaflet: Hypermap dependency (the map manufacturer’s own_ version 11.0.1)
    npm install leaflet: LeafletJS dependency (no need to download, the dependency will be automatically brought when downloading the Hypermap dependency)
  2. Generate a map (set center point, max zoom level, current zoom level, etc.)
  3. Punctuate on the map according to the latitude and longitude and punctuation icons in the data obtained from the search
  4. When searching data, first clear all punctuation, and then re-punctuate according to the searched data

4. Reference code

4.1 Installation dependencies

npm install @supermap/iclient-leaflet

4.2 Generate a map

  1. There must be a box for the map in the html

    <div id="map"></div>
    
    #map {
          
          
      position: absolute;
      top: 0;
      bottom: 0;
      width: calc(100% - 20px);
      border: 2px solid red; // 调页面添加的样式,看的清晰一点,之后会去掉
    }
    
  2. Introduce the css file in public/index.html

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.5.1/leaflet.css" />
    <link rel="stylesheet" href="https://iclient.supermap.io/dist/leaflet/iclient-leaflet.min.css" />
    

    The above method of importing css files is a bit cumbersome, just import the css in the leaflet dependency directly in the page that needs to use the css file

    import 'leaflet/dist/leaflet.css'
    

    [Note] Be sure to import the css file, otherwise the tiles from the map will be incomplete and the splicing of tiles will be messy
    insert image description here

  3. import dependencies

    import L from 'leaflet'
    import 'leaflet/dist/leaflet.css'
    import {
          
           tiledMapLayer } from '@supermap/iclient-leaflet'
    
  4. generate a map

    var url = 'https://iserver.supermap.io/iserver/services/map-china400/rest/maps/China'
    // var url = 'https://iserver.supermap.io/iserver/services/map-china400/rest/maps/China_4326'
    // var url = 'https://iserver.supermap.io/iserver/services/map-china400/rest/maps/ChinaDark'
    this.map = L.map('map', {
          
           // this.map初始值为 null
      center: [22.822074, 108.371154], // 中心点[经度, 纬度]
      maxZoom: 18, // 最大层级
      zoom: 11 // 当前层级
    })
    tiledMapLayer(url).addTo(this.map) // 添加地图(tiledMapLayer() 方法是地图厂商自己封装的,我们也可以用 LeafletJS 自己的方法进行地图的添加)
    
  5. Initial display of the map
    insert image description here

4.3 Punctuation_custom punctuation icon

  1. Do punctuation_preliminary implementation
    /**** 标记图标 start ****/
    var marker = L.marker([22.822074, 108.371154], {
          
           // L.marker([纬度, 经度], {})
      // 此处数据之后在 e.options 中可以取到
      title: '标点标记的title',
      clickable: true, // 是否可以点击
      draggable: false, // 是否可以拖拽
      icon: L.icon({
          
          
        iconUrl: 'https://api.map.baidu.com/lbsapi/getpoint/Images/logo.gif', // 标点图标地址
        iconSize: [50, 50] // 图标大小
      })
    }).on('click', (e) => {
          
          
      // 点击事件
      console.log('e----', e)
      console.log('"点击图标"----', '点击图标')
    })
    marker.bindPopup(`<span style="color:red;">我是点击图标时弹出框展示的内容</span>`).openPopup() // 由于要取当前标点信息,下边添加信息用 (e)=>{} 而不是直接写模板字符串
    marker.addTo(this.map) // 为了方便清除标点,下边添加标注点不用该方法
    /**** 标记图标 end ****/
    
    /**** 官网 ****/
    // L.marker([51.5, -0.09])
    //   .addTo(this.map)
    //   .bindPopup('A pretty CSS3 popup.<br> Easily customizable.')
    //   .openPopup()
    
    /**** 地图厂商封装 ****/
    // var marker = L.marker([纬度, 经度], { icon: markerIcon }).on('click', function (e) {
          
          
    //   L.popup().setLatLng(e.latlng).setContent(innerHTML2).openOn(map) // 通过popup添加点击弹出框
    // })
    
  2. Preliminary display of map point markers (the "Baidu icon" at the center of the map is the mark point)
    insert image description here
  3. Punctuate _ according to the returned data and style the display information pop-up box
    methods:{
          
          
    	// 加点标注
        addMakersToMap() {
          
          
          let layers = [] // 为添加、清除图标做准备【方法二_1】
          this.markers.forEach((item) => {
          
           // this.markers 为接口返回的需要进行标点的数据
            var marker = new L.marker([item.wd, item.jd], {
          
          
              title: item.jgmc,
              clickable: true,
              draggable: false,
              // opacity: 0.5, // 不透明度
              info: item, // 当前标点数据,点击图标展示信息时用
              icon: L.icon({
          
          
                iconUrl: `/images/${
            
            this.jglxIconObj[item.jglx]}.png`,
                iconSize: [30, 36]
              })
            }).on('click', (e) => {
          
           console.log('"点击图标"----', '点击图标') })
            
            /**** 点击图标弹出信息框 start ****/
            marker
              .bindPopup((e) => {
          
          
                console.log('点击图标 e----', e)
                return `<div class="popup">
                  <p class="title">${
            
             e.options.info.jgmc || '暂无' }</p>
                  <p><i class="iconfont ico-didian"></i><span>${
            
             e.options.info.jgdz || '暂无' }</span></p>
                  <p><i class="iconfont ico-yewu"></i><span>${
            
             e.options.info.kbyw || '暂无' }</span></p>
                  <p><i class="iconfont ico-dianhua"></i><span>${
            
             e.options.info.lxdh || '暂无' }</span></p>
                  <p><i class="iconfont ico-shijian"></i><span>${
            
             e.options.info.gzsj || '暂无' }</span></p>
                  <p><i class="iconfont ico-cheguansuo"></i><span>${
            
             e.options.info.jls || '暂无' }</span></p>
                  ${
            
             ['6', '7', '9', '11'].indexOf(e.options.info.jglx) > -1 ? `<p><i class="iconfont ico-yewuchuangkou"></i><span>${ 
               e.options.info.cks || '暂无' }</span></p>` : '' }
                  ${
            
             e.options.info.jglx === '1' ? `<p><i class="iconfont ico-diannao"></i><span>${ 
               e.options.info.kws || '暂无' }</span></p>` : '' }
                  ${
            
             ['2', '3'].indexOf(e.options.info.jglx) > -1 ? `<p><i class="iconfont ico-che"></i><span>${ 
               e.options.info.kcs || '暂无' }</span></p>` : '' }
                  ${
            
             e.options.info.jglx === '2' ? `<p><i class="iconfont ico-changdi"></i><span>${ 
               e.options.info.ksxls || '暂无' }</span></p>` : '' }
                  ${
            
             e.options.info.jglx === '3' ? `<p><i class="iconfont ico-malu"></i><span>${ 
               e.options.info.ksxls || '暂无' }</span></p>` : '' }
                  ${
            
             e.options.info.jglx === '4' ? `<p><i class="iconfont ico-jiancezhan"></i><span>${ 
               e.options.info.jcxs || '暂无' }</span></p>` : '' }
                  ${
            
             e.options.info.jglx === '5' ? `<p><i class="iconfont ico-chayan"></i><span>${ 
               e.options.info.cytds || '暂无' }</span></p>` : '' }
                </div>`
              })
              .openPopup()
            /**** 点击图标弹出信息框 end ****/
    
            // marker.addTo(this.map) // 将图标添加到地图上【方法一】(由于还要清除图标,所以不用该方法添加图标,用方法二)
            layers.push(marker) // 【方法二_2】
          })
          this.layerGroup = L.layerGroup(layers); // this.layerGroup 初始值为 null【方法二_3】
          this.map.addLayer(this.layerGroup) // 将图标添加到地图上【方法二_4】
        },
    }
    
    <style lang='scss' scoped>
    #map {
          
          
      position: absolute;
      top: 0;
      bottom: 0;
      width: calc(100% - 20px);
    
      border: 2px solid red;
    }
    /* 去掉原本点击图标展示对话框样式 */
    ::v-deep .leaflet-popup-content-wrapper,
    ::v-deep .leaflet-popup-tip {
          
          
      background-color: transparent;
      box-shadow: unset;
    }
    ::v-deep .leaflet-popup-close-button {
          
          
      display: none;
    }
    </style>
    
    <style lang="scss">
    #MapHome {
          
          
      /* 自己写 点击图标显示图标信息 对话框的样式 */
      .popup {
          
          
        position: absolute;
        left: 65px;
        top: 10px;
        width: 294px;
        font-family: 'MicroSoft Yahei';
        background: rgba(#000, 0.6);
        color: #fff;
        font-size: 14px;
        line-height: 30px;
        letter-spacing: 2px;
        text-align: left;
        p {
          
          
          padding: 0 12px;
          span {
          
          
            display: inline-block;
            width: calc(100% - 30px);
            vertical-align: top;
          }
          .iconfont {
          
          
            display: inline-block;
            margin-right: 6px;
            color: rgba(#fff, 0.5);
            &.ico-chepai::before {
          
          
              margin-left: -4px;
            }
          }
        }
        .title {
          
          
          padding: 2px 12px;
          background: rgba(#fff, 0.2);
          font-size: 16px;
          line-height: 40px;
          text-align: center;
        }
        .btns {
          
          
          border-top: 1px solid rgba(#fff, 0.2);
          .el-button {
          
          
            display: inline-block;
            width: calc((100% - 17px) / 2);
            color: #3ac7e0;
            &.warning {
          
          
              color: #ffb555;
            }
          }
          .el-divider {
          
          
            background-color: rgba(#fff, 0.2);
          }
        }
        .popCorner {
          
          
          position: absolute;
          width: 0;
          height: 0;
          &.cornerRT {
          
          
            border-top: 10px solid transparent;
            border-bottom: 10px solid transparent;
            border-left: 10px solid rgba(#000, 0.46);
            right: -10px;
            top: 10px;
          }
          &.cornerRB {
          
          
            border-top: 10px solid transparent;
            border-bottom: 10px solid transparent;
            border-left: 10px solid rgba(#000, 0.6);
            right: -10px;
            bottom: 10px;
          }
          &.cornerLT {
          
          
            border-top: 10px solid transparent;
            border-bottom: 10px solid transparent;
            border-right: 10px solid rgba(#000, 0.46);
            left: -10px;
            top: 10px;
          }
          &.cornerLB {
          
          
            border-top: 10px solid transparent;
            border-bottom: 10px solid transparent;
            border-right: 10px solid rgba(#000, 0.6);
            left: -10px;
            bottom: 10px;
          }
        }
      }
    }
    </style>
    
  4. Punctuation display based on returned data
    insert image description here

4.4 Clear punctuation

  • Listening jglxSeleList(check box data_processed into an array and then pass parameters to the search interface) → first judge whether there is a value
    • Has a value_calling the method of marking points_clearing all marking points_acquiring new data_re-marking points according to the new data
    • No value_current page if there are tags_clear all tags
    watch() {
          
          
    	jglxSeleList: {
          
          
          handler(val) {
          
          
            if (val && this.map) {
          
          
              this.queryParam.jglx = this.jglx2Str(val) // 将所有的复选框数据转为一个数组
              
              if (this.queryParam.jglx.length === 0) {
          
          
                // this.map.iclear()
                if(this.layerGroup !== null) this.layerGroup.clearLayers() // 移除所有标记
              } else {
          
          
                this.fetchMonDeptConfigList() // 获取新的I标记点的数据
              }
            }
          },
          immediate: true,
          deep: true
        },
    },
    methods: {
          
          
    	fetchMonDeptConfigList() {
          
          
          console.log('获取机构list 11111----', 11111)
          if (this.map) {
          
          
            if(this.layerGroup !== null) this.layerGroup.clearLayers() // 移除所有标记
          }
          fetchMonDeptConfigList(this.queryParam).then((res) => {
          
          
            console.log('获取机构list res----', res)
            this.common.CheckCode(res, null, () => {
          
          
              if (res.data && res.data.length > 0) {
          
          
                this.markers = res.data // 获取到新的标记点数据
                this.addMakersToMap() // 重新添加标记点
                this.map.panTo(new L.LatLng(this.markers[0].wd, this.markers[0].jd))  // 重新设置中心点(第一个标点数据为中心点)
              } else {
          
          
                this.$message({
          
          
                  type: 'info',
                  message: '未查询到相关机构网点'
                })
              }
            })
          })
        },
    }
    

5. APIs used

  1. punctuationlet maeker = new L.marker()
    • Click the punctuation icon - display content:marker.bindPopup('展示文字').openPopup()
    • Add the group of the layer:this.layerGroup = L.layerGroup(layers);
    • Add layers:this.map.addLayer(this.layerGroup)
    • Clear all markers:this.layerGroup.clearLayers()
    • Clear a marker: this.map.removeLayer(this.layer)not covered in this article
      • this.layer is L.polygon([[经度, 纬度],...], {color:'blue',fillColor:'none',opacity: 0.2 }(latitude and longitude are two-dimensional data, actually the api of the line, opacity: transparency, fileColor: fill color, color: border color)
      • Add markerthis.map.addLayer(this.layer);
  2. Set the center point of the map
    • this.map.panTo(new L.LatLng(纬度, 经度))

6. Overall code + page display

  • overall code
    <!-- 地图 - new - 参照地图厂商demo写的 -->
    <template>
      <div id="MapHome">
        <div class="queryDiv">
          <el-input
            placeholder="通过机构关键字查询"
            suffix-icon="iconfont ico-chaxun"
            v-model="jggjz"
          ></el-input>
        </div>
    
        <el-checkbox-group v-model="jglxSeleList">
          <el-collapse v-model="activeNames" class="jglxCon" accordion>
            <el-collapse-item v-for="(item, index) in jglxList" :name="item.name" :key="item.key">
              <template slot="title">
                <el-checkbox
                  class="checkAll"
                  v-model="item.allCheck"
                  :checked="item.allCheck"
                  @change="handleCheckAll(item.allCheck, index)"
                  :label="item.key"
                ></el-checkbox>
                <p class="title">
                  <span class="pdl20">{
         
         { item.name }}</span>
                  <span class="floatR">{
         
         { item.count }}</span>
                </p>
              </template>
              <el-checkbox
                v-for="obj in item.xllist"
                :key="obj.key"
                :label="obj.key"
                name="jglxSeleList"
              >
                <i :class="['iconfont', obj.icon]"></i>
                <span>{
         
         { obj.name }}</span>
                <span class="floatR">{
         
         { obj.count }}</span>
              </el-checkbox>
              <!--  -->
            </el-collapse-item>
          </el-collapse>
        </el-checkbox-group>
        <!-- <cdt-map @result="mapInit"></cdt-map> -->
        <div id="map"></div>
      </div>
    </template>
    
    <script>
    import {
            
             mapGetters } from 'vuex'
    // import CdtMap from '@/components/cdt-map/index'
    import {
            
             fetchMonDeptConfigList, queryMonDeptCount } from '@/api/service.js'
    
    import L from 'leaflet'
    import 'leaflet/dist/leaflet.css'
    import {
            
             tiledMapLayer } from '@supermap/iclient-leaflet'
    
    export default {
            
            
      name: 'Map',
      components: {
            
            
        // CdtMap
      },
      data() {
            
            
        return {
            
            
          map: null,
          jggjz: '', // 机构关键字
          markers: [],
          jgdlList: [],
          jglxList: [],
          jglxIconObj: {
            
            },
          jglxSeleList: [], // 选中显示的机构类型
          activeNames: [], // 下拉框展开
          activeItem: {
            
            }, // 选中的网点
          cornerType: '', // 弹框角标
          flag1: false, //
          flag2: false, // 地图初始化成功
          queryParam: {
            
            }, // 查询条件
          layerGroup: null // 地图标点图标
        }
      },
      computed: {
            
            
        ...mapGetters(['sysList'])
      },
      watch: {
            
            
        jglxSeleList: {
            
            
          handler(val) {
            
            
            if (val && this.map) {
            
            
              this.queryParam.jglx = this.jglx2Str(val)
    
              if (this.queryParam.jglx.length === 0) {
            
            
                if (this.layerGroup !== null) this.layerGroup.clearLayers() // 移除所有标记
              } else {
            
            
                this.fetchMonDeptConfigList()
              }
            }
          },
          immediate: true,
          deep: true
        },
        jggjz: {
            
            
          handler(val) {
            
            
            if (this.map) {
            
            
              if (val) {
            
            
                this.queryParam = {
            
            
                  jgmc: val
                }
              } else {
            
            
                this.queryParam = {
            
            
                  jglx: this.jglx2Str(this.jglxSeleList)
                }
              }
              this.fetchMonDeptConfigList()
            }
          },
          immediate: true,
          deep: true
        }
      },
    
      mounted() {
            
            
        this.queryMonDeptCount() // 地图首页机构数量统计接口
        this.mapInit()
      },
    
      methods: {
            
            
        mapInit() {
            
            
          console.log('"init start"----', 'init start')
          var url = 'https://iserver.supermap.io/iserver/services/map-china400/rest/maps/China'
          // var url = 'https://iserver.supermap.io/iserver/services/map-china400/rest/maps/China_4326'
          // var url = 'https://iserver.supermap.io/iserver/services/map-china400/rest/maps/ChinaDark'
          this.map = L.map('map', {
            
            
            center: [22.822074, 108.371154],
            maxZoom: 18,
            zoom: 11
          })
    
          tiledMapLayer(url).addTo(this.map)
          console.log('"init end"----', 'init end')
        },
    
        // 加点标注
        addMakersToMap() {
            
            
          let layers = [] // 为清除图标做准备
          this.markers.forEach((item) => {
            
            
            var marker = new L.marker([item.wd, item.jd], {
            
            
              title: item.jgmc,
              clickable: true,
              draggable: false,
              // opacity: 0.5, // 不透明度
              info: item, // 当前标点数据,点击图标展示信息时用
              icon: L.icon({
            
            
                iconUrl: `/images/${ 
              this.jglxIconObj[item.jglx]}.png`,
                iconSize: [30, 36]
              })
            }).on('click', (e) => {
            
            
              console.log('e----', e)
              console.log('"点击图标"----', '点击图标')
            })
    
            /**** 点击图标弹出信息框 start ****/
            marker
              .bindPopup((e) => {
            
            
                console.log('点击图标 e----', e)
                return `<div class="popup">
                  <p class="title">${ 
               e.options.info.jgmc || '暂无' }</p>
                  <p><i class="iconfont ico-didian"></i><span>${ 
               e.options.info.jgdz || '暂无' }</span></p>
                  <p><i class="iconfont ico-yewu"></i><span>${ 
               e.options.info.kbyw || '暂无' }</span></p>
                  <p><i class="iconfont ico-dianhua"></i><span>${ 
               e.options.info.lxdh || '暂无' }</span></p>
                  <p><i class="iconfont ico-shijian"></i><span>${ 
               e.options.info.gzsj || '暂无' }</span></p>
                  <p><i class="iconfont ico-cheguansuo"></i><span>${ 
               e.options.info.jls || '暂无' }</span></p>
                  ${ 
               ['6', '7', '9', '11'].indexOf(e.options.info.jglx) > -1 ? `<p><i class="iconfont ico-yewuchuangkou"></i><span>${ 
                 e.options.info.cks || '暂无' }</span></p>` : '' }
                  ${ 
               e.options.info.jglx === '1' ? `<p><i class="iconfont ico-diannao"></i><span>${ 
                 e.options.info.kws || '暂无' }</span></p>` : '' }
                  ${ 
               ['2', '3'].indexOf(e.options.info.jglx) > -1 ? `<p><i class="iconfont ico-che"></i><span>${ 
                 e.options.info.kcs || '暂无' }</span></p>` : '' }
                  ${ 
               e.options.info.jglx === '2' ? `<p><i class="iconfont ico-changdi"></i><span>${ 
                 e.options.info.ksxls || '暂无' }</span></p>` : '' }
                  ${ 
               e.options.info.jglx === '3' ? `<p><i class="iconfont ico-malu"></i><span>${ 
                 e.options.info.ksxls || '暂无' }</span></p>` : '' }
                  ${ 
               e.options.info.jglx === '4' ? `<p><i class="iconfont ico-jiancezhan"></i><span>${ 
                 e.options.info.jcxs || '暂无' }</span></p>` : '' }
                  ${ 
               e.options.info.jglx === '5' ? `<p><i class="iconfont ico-chayan"></i><span>${ 
                 e.options.info.cytds || '暂无' }</span></p>` : '' }
                  <div :class="['popCorner', cornerType]"></div>
                </div>`
              })
              .openPopup()
            /**** 点击图标弹出信息框 end ****/
    
            // marker.addTo(this.map) // 将图标添加到地图上【方法一】(由于还要清除图标,所以不用该方法添加图标)
            layers.push(marker)
          })
          this.layerGroup = L.layerGroup(layers)
          this.map.addLayer(this.layerGroup) // 将图标添加到地图上【方法二】
        },
    
        // 地图首页机构数量统计接口
        queryMonDeptCount() {
            
            
          queryMonDeptCount().then((res) => {
            
            
            this.common.CheckCode(res, null, () => {
            
            
              let jglxList = res.data
              jglxList.map((item) => {
            
            
                return (item.allCheck = true)
              })
              this.jglxList = jglxList
              this.jglxList.forEach((item) => {
            
            
                this.jgdlList.push(item.key)
                item.xllist.forEach((obj) => {
            
            
                  this.jglxSeleList.push(obj.key)
                  this.jglxIconObj[obj.key] = obj.icon
                })
              })
              this.flag1 = true
            })
          })
        },
    
        // 获取机构list
        fetchMonDeptConfigList() {
            
            
          if (this.map) {
            
            
            if (this.layerGroup !== null) this.layerGroup.clearLayers() // 移除所有标记
          }
          fetchMonDeptConfigList(this.queryParam).then((res) => {
            
            
            this.common.CheckCode(res, null, () => {
            
            
              if (res.data && res.data.length > 0) {
            
            
                this.markers = res.data
                this.addMakersToMap()
                this.map.panTo(new L.LatLng(this.markers[0].wd, this.markers[0].jd)) // 取第一条标点数据的经纬度作为地图的中心点
              } else {
            
            
                this.$message({
            
            
                  type: 'info',
                  message: '未查询到相关机构网点'
                })
              }
            })
          })
        },
    
        // 获取jglx to string
        jglx2Str(val) {
            
            
          let jglx = val.filter((item) => {
            
            
            if (this.jgdlList.indexOf(item) < 0) {
            
            
              return item
            }
          })
          return jglx.join(',')
        },
    
        addArr(val) {
            
            
          let flag = false
          for (let i = 0; i < this.jglxSeleList.length; i++) {
            
            
            if (this.jglxSeleList[i] === val) {
            
            
              flag = true
              break
            }
          }
          if (!flag) {
            
            
            this.jglxSeleList.push(val)
          }
        },
        cutArr(val) {
            
            
          for (let i = 0; i < this.jglxSeleList.length; i++) {
            
            
            if (this.jglxSeleList[i] === val) {
            
            
              this.jglxSeleList.splice(i, 1)
              break
            }
          }
        },
        // 全选/反选
        handleCheckAll(val, index) {
            
            
          this.jglxList[index].allCheck = !val
          if (this.jglxList[index].allCheck) {
            
            
            this.jglxList[index].xllist.forEach((row) => {
            
            
              this.addArr(row.key)
            })
          } else {
            
            
            this.jglxList[index].xllist.forEach((row) => {
            
            
              this.cutArr(row.key)
            })
          }
          this.$forceUpdate()
        }
      }
    }
    </script>
    
    <style lang='scss' scoped>
    #map {
            
            
      position: absolute;
      top: 0;
      bottom: 0;
      width: calc(100% - 20px);
    
      border: 2px solid red;
    }
    /* 去掉原本点击图标展示对话框样式 */
    ::v-deep .leaflet-popup-content-wrapper,
    ::v-deep .leaflet-popup-tip {
            
            
      background-color: transparent;
      box-shadow: unset;
    }
    ::v-deep .leaflet-popup-close-button {
            
            
      display: none;
    }
    </style>
    
    <style lang="scss">
    #MapHome {
            
            
      $colorList: #063b7f, #4a7feb, #33a8e4, #1da8ad, #e88e19, #e75748;
      $color1: #063b7f;
      $color2: #4a7feb;
      $color3: #33a8e4;
      $color4: #1da8ad;
      $color5: #e88e19;
      $color6: #e75748;
      width: 100%;
      height: 100%;
      .queryDiv {
            
            
        position: absolute;
        left: 80px;
        top: 20px;
        width: 380px;
        z-index: 999;
        .el-input {
            
            
          .el-input__inner {
            
            
            border: none;
            padding-right: 60px;
            height: 60px;
            box-shadow: 3px 3px 5px #ccc;
          }
          .el-input__suffix {
            
            
            right: 12px;
            .el-input__icon {
            
            
              width: 45px;
              font-size: 42px;
              line-height: 60px;
            }
          }
        }
      }
      .jglxCon {
            
            
        position: absolute;
        left: 80px;
        top: 96px;
        width: 226px;
        z-index: 999;
        .el-collapse-item {
            
            
          margin-bottom: 8px;
          .el-collapse-item__header {
            
            
            height: 40px;
            border-radius: 8px;
            border-bottom: none !important;
            padding: 0 10px;
            color: #fff;
            &.is-active {
            
            
              height: 40px;
              border-bottom: 1px solid rgba(#fff, 0.5) !important;
              border-radius: 8px 8px 0 0;
              transition: transform 0.3s;
            }
            .title {
            
            
              width: calc(100% - 16px);
              text-align: left;
            }
            .pdl20 {
            
            
              padding-left: 26px;
            }
            .el-collapse-item__arrow {
            
            
              position: absolute;
              left: 30px;
            }
            .el-checkbox__label {
            
            
              // color: transparent!important;
              display: none;
            }
            .el-checkbox.is-checked {
            
            
              background: none !important;
            }
          }
          .el-collapse-item__wrap {
            
            
            // padding: 6px 0;
            border-radius: 0 0 8px 8px;
            .el-checkbox {
            
            
              display: block;
              margin-right: 0;
              padding: 0 10px;
              width: 100%;
              text-align: left;
              color: #fff;
              letter-spacing: 2px;
              line-height: 30px;
              .el-checkbox__label {
            
            
                padding-left: 6px;
                width: calc(100% - 16px);
                .iconfont {
            
            
                  display: inline-block;
                  width: 20px;
                  color: rgba(#fff, 0.5);
                }
              }
            }
          }
          .el-checkbox.is-checked {
            
            
            .el-checkbox__label,
            .iconfont {
            
            
              color: #fff;
            }
            .el-checkbox__inner {
            
            
              background-color: #fff;
              border-color: #fff;
            }
          }
          @each $c in $colorList {
            
            
            $i: index($colorList, $c); // 获取索引
            &:nth-child(#{
            
            $i}) {
            
            
              .el-collapse-item__header {
            
            
                background: $c;
              }
              .el-collapse-item__wrap {
            
            
                background: rgba($c, 0.7);
              }
              .el-checkbox.is-checked {
            
            
                background: rgba($c, 0.85);
                .el-checkbox__inner::after {
            
            
                  border-color: $c;
                }
              }
            }
          }
        }
      }
      .popup {
            
            
        position: absolute;
        left: 65px;
        top: 10px;
        width: 294px;
        font-family: 'MicroSoft Yahei';
        background: rgba(#000, 0.6);
        color: #fff;
        font-size: 14px;
        line-height: 30px;
        letter-spacing: 2px;
        text-align: left;
        p {
            
            
          padding: 0 12px;
          span {
            
            
            display: inline-block;
            width: calc(100% - 30px);
            vertical-align: top;
          }
          .iconfont {
            
            
            display: inline-block;
            margin-right: 6px;
            color: rgba(#fff, 0.5);
            &.ico-chepai::before {
            
            
              margin-left: -4px;
            }
          }
        }
        .title {
            
            
          padding: 2px 12px;
          background: rgba(#fff, 0.2);
          font-size: 16px;
          line-height: 40px;
          text-align: center;
        }
        .btns {
            
            
          border-top: 1px solid rgba(#fff, 0.2);
          .el-button {
            
            
            display: inline-block;
            width: calc((100% - 17px) / 2);
            color: #3ac7e0;
            &.warning {
            
            
              color: #ffb555;
            }
          }
          .el-divider {
            
            
            background-color: rgba(#fff, 0.2);
          }
        }
        .popCorner {
            
            
          position: absolute;
          width: 0;
          height: 0;
          &.cornerRT {
            
            
            border-top: 10px solid transparent;
            border-bottom: 10px solid transparent;
            border-left: 10px solid rgba(#000, 0.46);
            right: -10px;
            top: 10px;
          }
          &.cornerRB {
            
            
            border-top: 10px solid transparent;
            border-bottom: 10px solid transparent;
            border-left: 10px solid rgba(#000, 0.6);
            right: -10px;
            bottom: 10px;
          }
          &.cornerLT {
            
            
            border-top: 10px solid transparent;
            border-bottom: 10px solid transparent;
            border-right: 10px solid rgba(#000, 0.46);
            left: -10px;
            top: 10px;
          }
          &.cornerLB {
            
            
            border-top: 10px solid transparent;
            border-bottom: 10px solid transparent;
            border-right: 10px solid rgba(#000, 0.6);
            left: -10px;
            bottom: 10px;
          }
        }
      }
    }
    </style>
    
  • Show results
    insert image description here

Seven, error

After packaging - error 1:SyntaxError: Unexpected token ...

  • The above code runs normally in the Internet environment, but the following error will be reported in the intranet environment
    insert image description here

  • After looking for the reason for a day, I found that it was a problem with the dependency of the map manufacturer used @supermap/iclient-leaflet, which caused an error Uncaught SyntaxError: Unexpected token ...(this error is a grammatical error)

  • The reason for the error
    @supermap/iclient-leafletdepends on the useful ES6 syntax, which needs to be configured when the project is packaged

  • solve

    1. Configuration: Syntax conversion when the project is packaged (screenshot of the official website provided by the map manufacturer ↓↓↓)
      insert image description here
    • First install dependencies npm i babel-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime -Dand then configure
      insert image description here
      const fs = require('fs')
      const webpack = require('webpack')
      const path = require('path')  // 【主要代码】
      
      const APP_Version = 'V1.0.1'
      const Timestamp = new Date().getTime();  //当前时间为了防止打包缓存不刷新,所以给每个js文件都加一个时间戳
      module.exports = {
              
              
          // 基本路径
          publicPath: './',
          // 输出文件目录
          outputDir: 'superviseAppWeb',
      
          // 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。
          // assetsDir: '',
      
          //指定生成的 index.html 的输出路径 (相对于 outputDir)。也可以是一个绝对路径。
          indexPath: 'index.html',
      
          // 是否使用包含运行时编译器的 Vue 构建版本。设置为 true 后你就可以在 Vue 组件中使用 template 选项了,但是这会让你的应用额外增加 10kb 左右。
          runtimeCompiler: true,
      
          // 默认情况下 babel-loader 会忽略所有 node_modules 中的文件。如果你想要通过 Babel 显式转译一个依赖,可以在这个选项中列出来。
          transpileDependencies: [],
      
          // 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
          productionSourceMap: false,
      
          // eslint-loader 是否在保存的时候检查
          lintOnSave: true,
      
          // webpack配置
          // 如果这个值是一个对象,则会通过 webpack-merge 合并到最终的配置中。
          // 如果这个值是一个函数,则会接收被解析的配置作为参数。该函数及可以修改配置并不返回任何东西,也可以返回一个被克隆或合并过的配置版本。
          // see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
          chainWebpack: () => {
              
              
          },
          configureWebpack: {
              
              
              plugins: [
                  new webpack.DefinePlugin({
              
              
                      'process.env': {
              
              
                          BUILD_LOCAL: JSON.stringify(process.env.BUILD_LOCAL)
                      }
                  }),
                  // new webpack.ProvidePlugin({
              
              
                  //     $: "jquery",
                  //     jQuery: "jquery",
                  //     "windows.jQuery": "jquery"
                  // })
              ],
              output: {
              
               // 输出重构  打包编译后的 文件名称  【模块名称.版本号.时间戳】
                  filename: `[name].${
                
                APP_Version}.${
                
                Timestamp}.js`,
                  chunkFilename: `[name].${
                
                APP_Version}.${
                
                Timestamp}.js`
              },
              /**** 【主要代码】@supermap/iclient-leaflet 依赖打包配置(npm安装依赖) start ****/
              module: {
              
              
                rules: [{
              
              
                  // 使用babel-loader将ES6语法转换为ES5
                  test: /\.js$/,
                  include: [
                      path.resolve(__dirname, "node_modules/@supermap/iclient-common"),
                      path.resolve(__dirname, "node_modules/@supermap/iclient-leaflet"),
                      // 由于iClient对Elasticsearch的API进行了封装而Elasticsearch也使用了ES6的语法
                      path.resolve(__dirname, "node_modules/elasticsearch"),
                  ],
                  loader: 'babel-loader',
                  options: {
              
              
                    presets: ['@babel/preset-env'],
                    plugins: [
                        [
                            '@babel/plugin-transform-runtime',
                            {
              
              
                                absoluteRuntime: false,
                                corejs: false,
                                helpers: false,
                                regenerator: true,
                                useESModules: false
                            }
                        ]
                    ]
                  }
                }]
              }
              /**** @supermap/iclient-leaflet 依赖打包配置(npm安装依赖) end ****/
          },
          // vue-loader 配置项
      
          // css相关配置
          css: {
              
              
              // 是否使用css分离插件 ExtractTextPlugin
              extract: false,
              // 开启 CSS source maps?
              sourceMap: false,
              // css预设器配置项
              loaderOptions: {
              
              
                  sass: {
              
              
                      data: fs.readFileSync('src/styles/variables.scss', 'utf-8')
                  }
              },
              // 启用 CSS modules for all css / pre-processor files.
              modules: false
          },
      
          // 是否为 Babel 或 TypeScript 使用 thread-loader。该选项在系统的 CPU 有多于一个内核时自动启用,仅作用于生产构建。
          parallel: require('os').cpus().length > 1,
      
          // PWA 插件相关配置
          // see https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa
          pwa: {
              
              },
      
          // webpack-dev-server 相关配置
          devServer: {
              
              
              host: '0.0.0.0',
              port: 8080,
              https: false,
              hotOnly: false,
              open: true, // 自动打开浏览器
              proxy: {
              
              
                  "/etm/": {
              
              
                      target: "http://192.168.31.125:8094/etm/", // 缉查布控地图服务
                      changeOrigin: true,
                      pathRewrite: {
              
              "^/etm/": ""}
                  },
                  '/': {
              
              
                      ws: false, // proxy websockets
                      target: 'http://192.168.0.26:9000',
                      // target: 'http://192.168.11.209:9381', // 郑胡训
                      // target: 'http://192.168.11.139:9181', // 何斌
                    
                      // target: 'http://192.168.0.42:9999', // 获取token
                      // target: 'http://192.168.0.42:9181', 
      
                      // target: 'http://192.168.20.37:9181',
                      pathRewrite: {
              
              '^/': ''},
                      changeOrigin: true,
                      secure: false
                  }
              }
          },
          // 第三方插件配置
          pluginOptions: {
              
              
              // ...
          },
      }
      
    1. Do not use map manufacturer's dependencies @supermap/iclient-leafletUse leafletdependencies (that is, do not use the hypergraph encapsulation tiledMapLayer()method, use LeafletJS's own TileLayer()method) [not tried]

After packaging - error 2:TypeError: Cannot assign to read only property 'export' of object '#<Object>'

  • After error 1 was resolved, error 2 appeared,
    insert image description here
    and Baidu found that it was @babel/plugin-transform-runtimea dependency problem, which needs to be babel.config.jsaddedsourceType: 'unambiguous'
    // babel.config.js文件
    module.exports = {
          
          
      presets: [
        '@vue/app'
      ],
      plugins: ['@babel/plugin-proposal-nullish-coalescing-operator'],
      sourceType: 'unambiguous' // 【主要代码】
    }
    
    Reference: https://blog.csdn.net/qq_41619796/article/details/108076869

Intranet - Error 3:SyntaxError: Unexpected token , in JSON at position 10

insert image description here

Guess you like

Origin blog.csdn.net/m0_53562074/article/details/128301447