当前位置: 首页 > 工具软件 > box-cli-maker > 使用案例 >

Vue-CLI and Leaflet: 添加 marker, polyline, polygon

钱睿范
2023-12-01

(一)Vue-CLI and Leaflet:起步 - 在 Vue-CLI 中使用 Leaflet

(二)Vue-CLI and Leaflet:地图基本操作(放大,缩小,平移,定位等)

(三)Vue-CLI and Leaflet: 添加 marker, polyline, polygon

(四)Vue-CLI and Leaflet: 添加 tooltips 和 popup

(五)Vue-CLI and Leaflet: 点、线、面 绘制 与 量测

(六)Vue-CLI and Leaflet: 添加各类图图层 ( AGS, OGC )

(七)Vue-CLI and Leaflet: 图层控制基本功能的实现

(八)Vue-CLI and Leaflet: AGS 属性查询与点图查询

一、功能分析

​ WebGIS 中添加标记或者图形是很常见的功能,如查询结果的图文联动,定位标记点,点图查询等都以此功能展开。而添加graphics是一切图形显示,绘制,编辑等功能的基础。

二、代码实现

1)添加 marker

​ Leaflet 中 marker 对象构造较为简单,可在官网提供的 API 文档中可以看到的主要构造参数:

​ 其中最主要的较为中中的参数为 icon 是显示结果的关键参数,iconUrl

icon支持的图片格式,支持常用的 .jpg .png .gif

在我的项目中需要在 map.js 分别添加 icon 和 maker 的两个构方法:

// src/utils/map.js

const createIcon = options => {
  return $L.icon(options);
};

/**
 * 通过 [x, y] 坐标添加 Maker
 *
 * @param {Object} map
 * @param {Object} latLng
 * @param {Object} options
 * 
 */
const createMakerByXY = (map, coordinate, options = {}) => {
  let marker = $L.marker($L.latLng(coordinate[1], coordinate[0s]), options);
  marker.addTo(map);
  return marker;
};

复制代码

然后再我们的页面添加使用上述方法的功能,这里我添加一个新的组件,放置示例功能入口。

// src/componets/MapTools.vue

<template>
  <div class="map-tools">
    <ul>
      <li @click="$emit('marker')">Maker</li>
      <li @click="$emit('polyline')">Polyline</li>
      <li @click="$emit('polygon')">Polygon</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "mapNavigation"
};
</script>
<style lang="less">
.map-tools {
  position: absolute;
  right: 15px;
  top: 15px;
  z-index: 999;

  height: 36px;
  box-shadow: 0px 0px 50px 2px rgba(0, 0, 0, 0.35);
  background-color: #fff;
  ul {
    display: flex;
    padding: 0;
    margin: 0;
    list-style: none;

    li {
      padding: 0 15px;
      height: 36px;
      font-size: 13px;
      line-height: 36px;
      cursor: pointer;
    }

    li:hover {
      background-color: rgb(212, 224, 246);
    }
  }
}
</style>

复制代码
// src/views/Map.vue

<template>
  <div class="map-container">
    <div id="map-container"></div>
    <NavigationCtrl @zoomIn="zoomIn" @zoomOut="zoomOut" @resetMap="resetMap"></NavigationCtrl>

    <MapTools @marker="addMarker" @polyline="addPolyline" @polygon="addPolygon"></MapTools>
  </div>
</template>

<script>
// @ is an alias to /src
import NavigationCtrl from "@/components/NavigationCtrl.vue";
import MapTools from "@/components/MapTools.vue";

export default {
  name: "mapView",
  components: { NavigationCtrl, MapTools },
  data() {
    return {
      map: null,
      OSMUrl: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
    };
  },
  mounted() {
    this.map = this.$utils.map.createMap("map-container", {
      zoomControl: false
    });
    this.$utils.map.createTileLayer(this.map, this.OSMUrl, {});
    this.map.setView([51.505, -0.09], 13);
  },
  methods: {
    zoomIn() {
      this.map.zoomIn();
    },
    zoomOut() {
      this.map.zoomOut();
    },
    resetMap() {
      this.map.flyTo([51.505, -0.09], 13);
    },
    addMarker() {
      this.$utils.map.createMakerByXY(this.map, [51.505, -0.09]);
    },
    addPolyline() {},
    addPolygon() {}
  }
};
</script>
<style lang="less">
.map-container {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
}
#map-container {
  width: 100%;
  height: 100%;
}
</style>

复制代码

这里添加 marker 方法默认是可以不传入任何参数,Leaflet 会加载其默认的 marker 样式。但是如果我们如果直接调用刚刚写的 添加 marker 的方法,看不到地图视图中有Marker显示,在控制台中会出现某一个路径错误。其实是Leaflet 默认的 icon 的图片路径不对。倒是 Leaflet 加载默认marker失败

解决方法如下,添加到 src/utils/map.js

// src/utils/map.js

import "leaflet/dist/leaflet.css";
import $L from "leaflet";

// 解决 leaflet 默认 maker 无法显示的问题
import icon from "leaflet/dist/images/marker-icon.png";
import iconShadow from "leaflet/dist/images/marker-shadow.png";
let DefaultIcon = $L.icon({
  iconUrl: icon,
  shadowUrl: iconShadow
});
$L.Marker.prototype.options.icon = DefaultIcon;

......
复制代码

解决后效果

自定义 maker 样式,则先创建不同的icon,修改一下 Map.vue 中添加addMarker方法

// src/views/Map.vue

......

addMaker() {
      this.$utils.map.createMakerByXY(this.map, [-0.09, 51.505]);

      let gifIcon = this.$utils.map.createIcon({
        iconUrl: require("./../assets/images/sample.gif"),
        iconSize: [32, 32]
      });
      this.$utils.map.createMakerByXY(this.map, [-0.095, 51.505], {
        icon: gifIcon
      });

      let pnOrJpgIcon = this.$utils.map.createIcon({
        iconUrl: require("./../assets/images/tree.png"),
        iconSize: [52, 42]
      });
      this.$utils.map.createMakerByXY(this.map, [-0.09, 51.490], {
        icon: pngJpgIcon
      });
    }
    
......

复制代码

事实上我们在地图功能上经常说到的添加点、线、面。如果你使用过 ArcGIS API for Javascript ,里面 Graphic 类包括了点,线,面三个要素,有专门负责负责渲染的样式类。而 leaflet 中点要素对应是 Marker

2)添加 Polyline

​ Leaflet 中构造线要素,面要素中关键的是弄清楚的其构造参数中的第一个参数。第一个参数,决定了要素的形状位置,是一个坐标数组。这个坐标数组是也可以包含多个要素组成复合多线要素或是复合多边形。

MultiPolyline shapeSinglePolyline shape
[
[[45.51, -122.68],
[37.77, -122.43],
[34.04, -118.2]],
[[40.78, -73.91],
[41.83, -87.62],
[32.76, -96.72]]
]
[
[45.51, -122.68],
[37.77, -122.43],
[34.04, -118.2]
]

负责样式的参数都在放在第二个参数 options 中。详细参数 如 线条颜色,宽度,透明度等 请参考官网

map.js 中添加创建线要素的方法

// src/utils/map.js

/**
 * 创建线要素
 *
 * @param {Object} map
 * @param {Array} linePath
 * @param {Object} lineOpts
 */

const createPolyline = (map, linePath, lineOpts) => {
  let polyline = $L.polyline(linePath, lineOpts);
  polyline.addTo(map);
  return polyline;
};

复制代码

我这里在 map.vue 在添加 data 存放创建线的坐标数组

// src/views/map.vue
data() {
    return {
      singleLine: [
        [51.517288954651875, -0.16685485839843753],
        [51.51194758264939, -0.1474571228027344],
        [51.51878442657495, -0.13320922851562503],
        [51.530426064343594, -0.1419639587402344],
        [51.53640593191922, -0.11209487915039064]
      ],
      miltipleLine: [
        [
          [51.49282033577651, -0.11432647705078126],
          [51.48010001366223, -0.10265350341796876],
          [51.48084836613703, -0.08222579956054689],
          [51.49591970845512, -0.08239746093750001]
        ],
        [
          [51.47614423230301, -0.08909225463867188],
          [51.47571655971428, -0.05973815917968751],
          [51.4829864484029, -0.03398895263671876],
          [51.49025517833079, -0.008239746093750002],
          [51.477641054786694, 0.008583068847656252],
          [51.487796767005534, 0.021800994873046875]
        ]
      ]
    };
  }
复制代码

我这里在 map.vuemethod 存放创建线要素的方法

// src/views/map.vue

......

methods: {
 addPolyline() {
      let singleLineStyle = {
        stroke: true,
        color: "#de0000",
        weight: 3,
        opacity: 1
      };

      this.$utils.map.createPolyline(
        this.map,
        this.singleLine,
        singleLineStyle
      );

      let multipleLineStyle = {
        stroke: true,
        color: "#0085fb",
        weight: 4,
        opacity: 1
      };
      this.$utils.map.createPolyline(
        this.map,
        this.miltipleLine,
        multipleLineStyle
      );
    }
  }

......

复制代码

3)添加 Polygon

Polygon 的创建和Polyline的创建方法几乎是一样的,包括坐标串的组织方式也基本一样。

// src/utils/map.js

......

/**
 * 创建面要素
 * 
 * @param {Object} map 
 * @param {Array} areaPath 
 * @param {Object} areaOpts 
 */

const createPolygon = (map, areaPath, areaOpts) => {
  let polygon = $L.polyline(areaPath, areaOpts);
  polygon.addTo(map);
  return polygon;
};

......

复制代码

这里贴出文章中的展示的图形示例:

// src/views/map.vue

data() {
    return {
        singlePolygon: [
            [51.50203767899114, -0.13977527618408206],
            [51.505777518488806, -0.13072013854980472],
            [51.505109712517786, -0.1296043395996094],
            [51.50388092395907, -0.12921810150146487],
            [51.50345351147583, -0.12921810150146487],
            [51.50302609498369, -0.12947559356689456],
            [51.502545246638114, -0.12973308563232425],
            [51.50219796412198, -0.12990474700927737],
            [51.50177053585362, -0.12990474700927737],
            [51.5014232474337, -0.12999057769775393],
            [51.50043479667606, -0.13891696929931643],
            [51.50134310357634, -0.1399040222167969],
            [51.50195753621433, -0.13973236083984378],
            [51.50195753621433, -0.13973236083984378]
          ],
        miltiplePolygon: [
            [
              [51.481703611072156, -0.09407043457031251],
              [51.480313829908056, -0.09080886840820312],
              [51.481703611072156, -0.08531570434570314],
              [51.482131227525315, -0.07415771484375001],
              [51.48394855271953, -0.07415771484375001],
              [51.48426924964768, -0.07638931274414064],
              [51.486941636341456, -0.07604598999023438],
              [51.485552014806856, -0.07947921752929689],
              [51.48426924964768, -0.0830841064453125],
              [51.48320025111633, -0.08754730224609376],
              [51.4826657424533, -0.08943557739257814],
              [51.481489801341986, -0.09441375732421875],
              [51.481489801341986, -0.09441375732421875]
            ],
            [
              [51.49869827721546, -0.05613327026367188],
              [51.498377681772325, -0.05922317504882813],
              [51.49506473014368, -0.05802154541015626],
              [51.49132401147376, -0.05407333374023438],
              [51.49143089340988, -0.05184173583984376],
              [51.492072179764314, -0.05046844482421876],
              [51.49292721420453, -0.04978179931640626],
              [51.49388910878061, -0.04840850830078125],
              [51.49506473014368, -0.05149841308593751],
              [51.49602657961649, -0.05270004272460938],
              [51.49709527744871, -0.05373001098632813],
              [51.498484547170605, -0.05647659301757813],
              [51.49869827721546, -0.05699157714843751],
              [51.49762961696847, -0.06025314331054688],
              [51.49762961696847, -0.06025314331054688]
            ]
          ]
    };
  }

复制代码

这里需要提一下,添加线和面的的方法是直接绑定在工作组件上的。

// src/views/map.vue

<template>
  <div class="map-container">
    <div id="map-container"></div>
    <NavigationCtrl @zoomIn="zoomIn" @zoomOut="zoomOut" @resetMap="resetMap"></NavigationCtrl>
    <MapTools @maker="addMaker" @polyline="addPolyline" @polygon="addPolygon"></MapTools>
  </div>
</template>

复制代码

三)总结

​ 添加点、线、面功能的简单功能实现并不复杂,如果是从 ArcGIS API for Javascript 转过来的,可能开始会不适应。这里的展示的例子后面会放在gitHub上。如有疏漏或是错误请各位多多指教。

 类似资料: