安装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>