Vue2Leaflet(基于vue的leafLet)封装的图片打点功能 移动端与pc端同样适用【自用】

 安装leaflet

cnpm i leaflet -S

安装vue2-leaflet

cnpm i vue2-leaflet -S 

main.js中引入

Vue.config.productionTip = false

import 'leaflet/dist/leaflet.css';

<comment>
  平面图标记 
  传参说明 见props
</comment>
<template>
  <div id="leafLet">
    <l-map
      ref="map"
      :zoom="zoom"
      :min-zoom="minZoom"
      :max-zoom="maxZoom"
      :center="center"
      :crs="crs"
      :options="{zoomControl: false,zoomAnimationThreshold:20}"
      :max-bounds="bounds"
      style="width:100%;height:600px"
      @update:center="centerUpdate"
      @update:zoom="zoomUpdate"
    >
      <!-- 图片的图层 -->
      <template>
        <l-image-overlay
          :url="url"
          :bounds="bounds"
          :options="{interactive:true}"
          @click="addPoint"
        />
      </template>
      <!-- 标记图层 -->
      <template>
        <l-marker
          v-for="(point,index) in points"
          :key="index"
          :lat-lng="point"
          :visible="showPoint"
          :options="{permanent: true}"
        >
          <!-- <l-icon :icon-url="!point.old&&type=='edit'?warningIcon:primaryIcon" /> -->
          <l-tooltip
            :options="{permanent: true,interactive: true,offset: [0, -10],direction: 'center',className:!point.old&&type.includes('dit')?'label warning-label':'label primary-label'}"
          >
            <span>{{index+1}}</span>
          </l-tooltip>
        </l-marker>
      </template>
    </l-map>
    <div class="flex wrap" style="margin-top:20px" v-if="type!='detail'||readonly">
      <p
        v-for="(point,index) in points"
        :key="'c'+index"
        class="pointFlag"
        :class="currentId==index+1?'active':''"
        @click="positionClick(point,index)"
      >
        <label>{{index+1}}</label>
        <span
          class="closeFlag"
          @click.stop="removePoint(point,index)"
          v-if="currentId==index+1&&(!point.old||type!='newEdit')"
        >
          <i class="iconfont iconqingchu"></i>
        </span>
      </p>
    </div>
  </div>
</template>

<script>
import { CRS, latLng, icon, latLngBounds } from "leaflet";
import {
  LMap,
  LImageOverlay,
  LIcon,
  LMarker,
  LPopup,
  LPolyline,
  LTooltip
} from "vue2-leaflet";
delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
  iconRetinaUrl: require("leaflet/dist/images/marker-icon-2x.png"),
  iconUrl: require("leaflet/dist/images/marker-icon.png"),
  shadowUrl: require("leaflet/dist/images/marker-shadow.png")
});

export default {
  name: "Example",
  components: {
    LMap,
    LImageOverlay,
    LMarker,
    LPopup,
    LPolyline,
    LTooltip,
    LIcon
  },
  props: {
    // 平面图资源
    url: {
      type: String,
      default: () => {
        return require("./a.png");
      }
    },

    // type:add 添加点时用
    // type:edit 编辑点时用(原来的点可删除,新打的点为黄色)
    // type:newEdit 编辑点时用(原来的点不可操作,新打的点为黄色)
    // type:detail 不可操作,仅供查看使用
    type: {
      type: String,
      default: "add"
    },

    // 标记点位!!!!!!!
    /*当type为edit或者newEdit时,点数据需加属性old为true
    如下
    [
      { lat: 145.0, lng: 175.2, old: true },
      { lat: 130.1, lng: 41.6, old: true }
    ]
    lng:left
    lat:bottom
    */
    points: {
      type: Array,
      default: () => {
        return [
          // { lng: 0, lat: 100 },
          // { lng: 41.6, lat: 130.1 }
          { lng: 0, lat: 100, old: true },
          { lng: 41.6, lat: 130.1, old: true }
        ];
      }
    },
    //是否单个标点 只能标一个点
    single: {
      type: Boolean,
      default: false
    },
    //平面图区域的宽
    width: {
      type: String,
      default: "100%"
    },
    //平面图区域的高
    height: {
      type: String,
      default: "600px"
    },
    // 是否显示标点
    showPoint: {
      type: Boolean,
      default: true
    },
    //图片下面的点位列表是否可以点击
    // 只读模式  此属性和detail同效果 为了不影响以前的功能
    readonly: {
      type: Boolean,
      default: false
    }
  },
  model: {
    prop: "points",
    event: "change"
  },
  data() {
    return {
      center: [0, 0], //(中心):初始化地图的地理中心。
      zoom: -1, //Pc端设置为-1 移动端设置为-2(缩放):初始化地图的缩放。  
      minZoom: -2, //(最小视图):地图的最小视图。可以重写地图图层的最小视图。
      maxZoom: 20, //(最大视图):地图的最大视图。可以重写地图图层的最大视图。
      crs: CRS.Simple, //(坐标参考系统):使用的坐标系,当你不确定坐标系是什么时请不要更改。
      bounds: [[0, 0], [0, 0]], //(最大边界):当这个选项被设置后,地图被限制在给定的地理边界内,当用户平移将地图拖动到视图以外的范围时会出现弹回的效果,并且也不允许缩小视图到给定范围以外的区域(这取决于地图的尺寸);
      warningIcon: require("./warning.png"),
      primaryIcon: require("./primary.png"),
      currentId: ""
    };
  },
  created() {},
  watch: {
    url: {
      handler(newVal, oldVal) {
        this.imgLoad(newVal);
      },
      immediate: true,
      deep: true
    }
  },
  computed: {
    dynamicSize() {
      return [this.iconSize, this.iconSize * 1.15];
    },
    dynamicAnchor() {
      return [this.iconSize / 2, this.iconSize * 1.15];
    }
  },
  mounted() {},
  methods: {
    //图片加载完成事件
    imgLoad(url) {
      var img = new Image();
      img.src = url;
      if (img.complete) {
        this.initBounds(img.width, img.height);
      } else {
        img.onload = () => {
          this.initBounds(img.width, img.height);
          img.onload = null;
        };
      }
    },
    //初始化bounds 使图片超出可视区域后回弹
    initBounds(w, h) {
      this.bounds = [[0, 0], [h, w]];
    },
    //zoom的change事件
    zoomUpdate(zoom) {
      // console.log("zoom:" + zoom);
    },
    //center的change事件
    centerUpdate(center) {
      // console.log("center:" + center);
    },
    //添加点
    addPoint(data) {
      if (this.type == "detail" || this.readonly) {
        return;
      }
      if (this.single && this.points.length >= 1) {
        return;
      }
      let point = data.latlng;
      let star = {
        lat: point.lat,
        lng: point.lng
      };
      this.points.push(star);
      this.$emit("change", this.points);
    },
    //移除点
    removePoint(point, index) {
      this.points.splice(index, 1);
      this.$emit("change", this.points);
      this.currentId = "";
      this.$refs.map.mapObject.setView([0, 0], -1);//Pc端设置为-1 移动端设置为-2
    },
    //点位的点击事件
    positionClick(point, index) {
      this.currentId = index + 1;
      this.$refs.map.mapObject.setView([point.lat, point.lng], 5);
    }
  }
};
</script>
<style lang="scss">
#leafLet {
  .leaflet-container {
    background: #fff;
  }
  .flex {
    display: flex;
    min-width: 0;
  }

  .wrap {
    -ms-flex-wrap: wrap;
    flex-wrap: wrap;
  }

  .pointFlag {
    width: 14%;
    height: 50px;
    display: flex;
    justify-content: center;
    align-items: center;
    margin-left: 5px;
    margin-right: 5px;
    margin-bottom: 10px;
    background: #ddd;
    position: relative;
    &.active {
      background: #fff;
    }
    .closeFlag {
      position: absolute;
      right: -5px;
      top: -5px;
      width: 15px;
      height: 15px;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .closeFlag.active {
      background: #fff;
    }
  }
  //图片icon
  .leaflet-marker-icon {
    display: none;
  }
  //图片上点的样式
  .leaflet-tooltip {
    border: 1px solid transparent;
    box-shadow: none;
  }
  .label {
    height: 10px;
    min-width: 10px;
    font-size: 13px;
    display: flex;
    color: #fff;
    justify-content: center;
    align-items: center;
    border-radius: 50%;
  }
  .label:after {
    content: "";
    position: absolute;
    width: 0;
    height: 0;
    border-width: 8px;
    border-style: solid;
    bottom: -14px;
  }
  .primary-label {
    background: rgba(0, 128, 203, 1);
  }
  .primary-label:after {
    border-color: rgba(0, 128, 203, 1) transparent transparent transparent;
  }
  .warning-label {
    background: #ff8a1b;
  }
  .warning-label:after {
    border-color: #ff8a1b transparent transparent transparent;
  }
}
</style>
发布了248 篇原创文章 · 获赞 32 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/qq_37899792/article/details/103723009