Vue Mapbox-GL 在地图中增加图标、线条、标记点击弹窗、地图平移
vue
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
项目地址:https://gitcode.com/gh_mirrors/vu/vue
免费下载资源
·
最近正在搞Mapbox-GL地图的一系列东西,按照公司的需求,要做成离线地图(点击这里),然后要在地图的基础上进行增加图标标记,线条连接、弹窗等等需求。ok废话不多,往下看。
如果还没有安装mapbox-gl的小伙伴请先看一下上篇的离线地图的文章,这里不再重复写安装步骤了,直接上代码:
一、在地图上增加图标
<template>
<div>
<div class="mapBOX" id="map" ref="basicMapbox"></div>
</div>
</template>
<script>
let map;
import mapboxgl from 'mapbox-gl';
export default {
methods: {
this.initMap(){
let mapStyle = require('../../../static/style.json');// sytle.json看上一篇文章,或者使用官方的网址也可以:let mapStyle = "mapbox://styles/mapbox/streets-v11"
map = new mapboxgl.Map({
container: this.$refs.basicMapbox,
style: mapStyle,
// 中心点:北京市
center: [116.469000,40.251706],
zoom: 10,
minZoom: 3,
maxZoom: 15,
fadeDuration: 100,
antialias: true,
});
this.map.on('load', () => {
// 图片需要是网络地址,前端本地地址行不通
map.loadImage('http://ip/file/img/icon.png', (error, image) => {
if (error) throw error;
map.addImage('iconImage', image);
// 图标位置坐标
let features = [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [116.469000,40.251706]
}
}, {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [116.469000,40.351706]
}
}]
map.addSource('iconImage', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features
}
});
// 增加图片
map.addLayer({
id: "iconImage",
type: "symbol",
source: 'iconImage', // 对应addSource第一个参数名字
layout: {
"icon-image": "iconImage", // 对应addImage()第一个参数名字
"icon-size": 0.1,//图标的大小
},
})
}
},
mounted() {
this.initMap()
}
}
</script>
官网也有示例:
添加链接描述
二、在地图上画线条
<template>
<div>
<div class="mapBOX" id="map" ref="basicMapbox"></div>
</div>
</template>
<script>
let map;
import mapboxgl from 'mapbox-gl';
export default {
methods: {
this.initMap(){
let mapStyle = require('../../../static/style.json');// sytle.json看上一篇文章,或者使用官方的网址也可以:let mapStyle = "mapbox://styles/mapbox/streets-v11"
map = new mapboxgl.Map({
container: this.$refs.basicMapbox,
style: mapStyle,
// 中心点:北京市
center: [116.469000,40.251706],
zoom: 10,
minZoom: 3,
maxZoom: 15,
fadeDuration: 100,
antialias: true,
});
map.on('load', () => {
map.addSource('lineSource', {
type: 'geojson',
data: {
type: "FeatureCollection",
features: [{
type: "Feature",
geometry: {
type: 'LineString',
coordinates: [
[116.469000,40.251706],
[116.469000,40.351706],
[117.469000,40.351706]
],
}
},
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [116.469000,40.251706]
}
},
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [116.469000,40.351706]
}
},
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [117.469000,40.351706]
}
},
]
}
});
// 增加线条
map.addLayer({
id: "lines",
type: "line",
source: "lineSource",
layout: {
line-cap: "round",
line-join: "round",
},
paint: {
"line-width": 3, // 线条宽度
"line-opacity": 1, // 线条透明度
"line-color": "#000000", // 线条颜色
}
});
// 显示线路节点
map.addLayer({
id: "lineSources",
type: "circle",
source: "lineSource",
paint: {
"circle-radius": 6, // 圆角值
"circle-color": "#000000" // 节点颜色
},
})
}
},
mounted() {
this.initMap()
}
}
</script>
三、地图点击标记点弹窗
这里参考复制了部分代码:
添加链接描述
官网API:
添加链接描述
<template>
<div>
<div class="mapBOX" id="map" ref="basicMapbox"></div>
</div>
</template>
<script>
let map;
import Vue from "vue";
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css'; // 最近发现的问题,如果样式没出来,请加上这句
import InfoPopup from "./components/info-popup.vue";
export default {
components: { InfoPopup },
methods: {
this.initMap(){
let mapStyle = require('../../../static/style.json');// sytle.json看上一篇文章,或者使用官方的网址也可以:let mapStyle = "mapbox://styles/mapbox/streets-v11"
map = new mapboxgl.Map({
container: this.$refs.basicMapbox,
style: mapStyle,
// 中心点:北京市
center: [116.469000,40.251706],
zoom: 10,
minZoom: 3,
maxZoom: 15,
fadeDuration: 100,
antialias: true,
});
map.on('load', () => {
this.openPopup()
});
},
// 地图标记点弹窗
openPopup(coordinate = [116.469000,40.251706]) {
let el = document.createElement('div')
el.id = 'markerId'
el.style.backgroundColor= '#6699ff'
el.style.width = 20 + 'px'
el.style.height = 20 + 'px'
el.style.borderRadius = '50%'
let marker = new mapboxgl.Marker(el).setLngLat(coordinate).setOffset([0, -19]).addTo(map) // 将标记添加到地图上
this.currentMarkers.push(marker)
// 添加弹窗
const popDetail = Vue.extend(InfoPopup)
let vm = new popDetail({
propsData: {
color: '#6699ff',
name: 'xxx',
},
})
vm.$mount() //挂载
let popupTemp = vm.$el
// 添加弹窗
var popup = new mapboxgl.Popup({ closeButton: false, offset: 25, className: 'map-popup' }).setDOMContent(popupTemp)
new mapboxgl.Marker(el)
.setLngLat(coordinate)
.setPopup(popup)
.addTo(map)
},
},
mounted() {
this.initMap()
}
}
</script>
InfoPopup组件:
<!-- 地图弹窗 -->
<template>
<div class="info-popup">
<div class="info-popup-content">
{{ name }}
</div>
</div>
</template>
<script>
export default {
name: '',
props: {
// 显示名称
name: {
type: String,
default: '名称'
}
},
data() {
return {
}
}
};
</script>
<style lang='less' scoped>
.info-popup {
border-radius: 10px;
font-family: "Microsoft YaHei";
}
</style>
四、再附上一些可能用到的方法
- 鼠标经过事件
map.on('mouseenter', 'addLayer的id值', (e) => {
console.log('e', e);
});
- 鼠标点击事件
map.on('click', 'addLayer的id值', (e) => {
console.log('e', e);
});
- 地图平移
// center为要平移的坐标,zoom为平移的缩放级别
map.flyTo({ center:[坐标], zoom: 9 });
父组件
// 添加弹窗
const popDetail = Vue.extend(PopupInfo)
let vm = new popDetail({
propsData: {
name,
details,
},
methods:{
closePopup(){
//触发关闭弹框
this.$emit('close-popup');
}
}
})
// 在父组件中监听子组件触发的事件
vm.$on('close-popup', () => {
// 在这里执行关闭弹框的操作
this.popup && this.popup.remove();
});
vm.$mount() //挂载
// 添加弹窗
this.popup = new maplibregl.Popup({ closeButton: false, offset: 25, className: 'map-popup' }).setDOMContent(vm.$el)
new maplibregl.Marker(ele)
.setLngLat(coord)
.setPopup(this.popup)
.addTo(this.map)
//子组件
<template>
<div class="detail-popupInfo">
<span class="detail-popupInfo__title" v-text="name"></span>
<div class="detail-popupInfo__content" @onWheel="(e)=>e.stopPropagation()">
<i class="el-icon-close detail-popupInfo__close" @click="close"></i>
</div>
</div>
</template>
<script>
export default {
name: "PopupInfo",
components: {},
props: {
name: {
type: String,
default: ''
},
details: {
type: Array,
default: []
}
},
data() {
return {
};
},
created() {
},
mounted() {
},
beforeDestroy() {
},
methods: {
close(){
this.closePopup();
}
}
}
</script>
<style scoped lang="scss">
</style>
最后,react版本
// 详情弹窗
let popEle = document.createElement('div');
const popupMaker = new mapboxgl.Marker({ element: popEle, anchor: 'center', offset: [0, 0] });
//子组件
const DetailPopup = ({ name, details }) => {
return (
<div className="detail-popup">
<span className="detail-popup__title">{name}</span>
<div className="detail-popup__content" onWheel={(e) => e.stopPropagation()}>
<CloseOutlined
className="detail-popup__close"
onClick={() => ReactDOM.unmountComponentAtNode(popEle)}
/>
<article className="detail-popup__ul">
{details.map((item, index) => (
<p className="serial" key={index}>
<span className="dot">●</span>
<span className="name">{item.mnx}</span>
</p>
))}
</article>
</div>
</div>
);
};
// 飞线结束位置
flyArr.forEach(({ name, coord }) => {
const properties = flyArrData.features.map((item) => item.properties);
const details = properties.find((item) => item.name === name)?.details || [];
let ele = document.createElement('div');
ele.innerHTML = `
<div class="line-end-maker" >
<div class="line-end-maker__title" >${name}</div>
<div class="line-end-maker__point" />
</div>
`;
new mapboxgl.Marker({ element: ele, anchor: 'center', offset: [0, 0] })
.setLngLat(coord)
.addTo(map);
// 详情弹窗
ele.addEventListener('click', () => {
// 点击之后再添加到map上
popupMaker.remove().setLngLat(coord).addTo(map);
//父组件
ReactDOM.unmountComponentAtNode(popEle);
ReactDOM.render(<DetailPopup name={name} details={details} />, popEle);
});
});
GitHub 加速计划 / vu / vue
80
16
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:4 个月前 )
73486cb5
* chore: fix link broken
Signed-off-by: snoppy <michaleli@foxmail.com>
* Update packages/template-compiler/README.md [skip ci]
---------
Signed-off-by: snoppy <michaleli@foxmail.com>
Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 6 个月前
e428d891
Updated Browser Compatibility reference. The previous currently returns HTTP 404. 6 个月前
更多推荐
已为社区贡献8条内容
所有评论(0)