npm i ol -s
npm i axios -s
<template>
<div class="my-add-maker-box">
<div class="my-point-box">
<span>经度lng:</span>
<el-input v-model.trim="pointData.lng" :disabled="true" placeholder="请点击下面地图进行标注" />
<span>纬度lat:</span>
<el-input v-model.trim="pointData.lat" :disabled="true" placeholder="请点击下面地图进行标注" />
</div>
<div class="my-map-box" id="map" :key="keyMap">
<div class="my-map-search">
<el-input v-model="param.data.postStr.keyWord" placeholder="请输入地名">
<template #append>
<el-button :icon="Search" @click="searchHandle" />
</template>
</el-input>
<div class="my-map-clear" @click="clearMarker">清除标注</div>
<div class="my-search-result" v-if="searchShow">
<div v-if="searchResult.data == null" style="margin-left: 150px; font-size: 20px; color: #888;">暂无数据</div>
<div v-else class="my-search-result-item" v-for="(item, index) in searchResult.data" :key="index"
@click="clickMarker(item)">{{ item.name }}
</div>
</div>
</div>
</div>
</div>
</template>
<script lang='ts' setup>
import { ref, reactive, onMounted } from 'vue'
//导入相关配置信息
import 'ol/css';
import { Map, View, Feature } from 'ol'
import { Style, Icon } from 'ol/style'
import { Point } from 'ol/geom';
import { Vector as SourceVec, XYZ, } from 'ol/source'
import { Vector as LayerVec } from 'ol/layer'
import TileLayer from 'ol/layer/Tile'
import { defaults as defaultControls, MousePosition, } from "ol/control"
import axios from 'axios'
import { Search } from '@element-plus/icons-vue'
let myMap: any = null
let myView: any = null
let keyMap: any = ref(Math.random())
let vectorLayer: any = null
let searchResult = reactive({ data: null })
let searchShow = ref(false)
let pointData = reactive({ lng: '', lat: '' })
// url
const url = ref('http://api.tianditu.gov.cn/v2/search')
// 参数
let param = reactive({
data: {
postStr: {
keyWord: '',
level: 18,
mapBound: "116.02524,39.83833,116.65592,39.99185",
queryType: 1,
start: 0,
count: 10
},
type: 'query',
tk: '37c72a79fe4c6a1b3fa6b1435214b378'
}
})
onMounted(() => {
// console.log('initMap')
setTimeout(() => {
myMap = new Map({
target: 'map',
//图层数组 layers
layers: [
new TileLayer({
source: new XYZ({
crossOrigin: 'anonymous',
url: 'https://t0.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=37c72a79fe4c6a1b3fa6b1435214b378'
})
}),
new TileLayer({
source: new XYZ({
crossOrigin: 'anonymous',
url: 'https://t0.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=37c72a79fe4c6a1b3fa6b1435214b378'
})
})
],
//视图 View
view: new View({
projection: "EPSG:4326",
center: [120.15373797456354, 30.291315691648734],
zoom: 15,
maxZoom: 17,
minZoom: 3,
}),
//默认控件
controls: defaultControls({
zoom: false,
rotate: false,
attribution: false,
}).extend([
//添加新控件
// new MousePosition(),
])
})
// 获取地图视图
myView = myMap.getView()
// setMarker([120.15373797456354, 30.291315691648734])
myMap.on('singleclick', function (e: any) {
setMarker(e.coordinate)
})
}, 1);
})
// 标注点
const setMarker = (point: any) => {
//移出给定的图层
myMap.removeLayer(vectorLayer)
// 创建矢量容器
let vectorSource = new SourceVec({})
//创建图标特性
let iconFeature = new Feature({
geometry: new Point(point, "XY")
})
//将图标特性添加进矢量中
vectorSource.addFeature(iconFeature)
//创建图标样式
let iconStyle = new Style({
image: new Icon({
opacity: 0.75,
src: require('@/assets/images/marker-icon.png'),
// offset: [-20, -40],
// offsetOrigin: 'bottom-right',
size: [30, 65]
})
})
//创建矢量层
vectorLayer = new LayerVec({
source: vectorSource,
style: iconStyle
}); //添加进map
// removeLayer
myMap.addLayer(vectorLayer);
param.data.postStr.keyWord = ''
searchShow.value = false
pointData.lng = point[0]
pointData.lat = point[1]
}
// 清除标注点
const clearMarker = () => {
//移出给定的图层
myMap.removeLayer(vectorLayer)
pointData.lng = ''
pointData.lat = ''
}
// 点中某个结果
const clickMarker = (item: object) => {
setMarker(item.lonlat.split(','))
myView.setCenter(item.lonlat.split(','))
param.data.postStr.keyWord = ''
searchShow.value = false
}
//搜索
const searchHandle = () => {
// 地名查询
axios({
method: 'GET',
url: url.value,
params: param.data
}).then(function (res) {
console.log(res.data.pois)
searchShow.value = true
if (res.data.pois) {
searchResult.data = res.data.pois
} else {
searchResult.data = null
}
console.log(res.data)
})
}
</script>
<style scoped lang='less'>
.my-add-maker-box {
width: 100vw;
// border: 1px solid #eee;
.my-point-box {
width: 900px;
margin: auto;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 20px;
span {
display: inline-block;
width: 200px;
}
}
.my-map-box {
width: 900px;
height: 500px;
margin: auto;
position: relative;
z-index: 1;
.my-map-search {
position: absolute;
top: 5px;
left: 10px;
z-index: 99;
.my-map-clear {
position: absolute;
top: 0;
left: 380px;
z-index: 999;
width: 90px;
text-align: center;
line-height: 30px;
border: 1px solid #dcdfe6;
background-color: #f5f7fa;
border-radius: 3px;
cursor: pointer;
color: #909399;
&:hover {
background-color: #ecf5ff;
color: #409eff;
}
}
.my-search-result {
position: absolute;
top: 31px;
left: 0;
z-index: 999;
width: 371px;
max-height: 260px;
border: 1px solid #eee;
box-sizing: border-box;
background-color: #fff;
overflow: auto;
padding: 10px 0;
.my-search-result-item {
width: 100%;
padding: 8px 15px;
box-sizing: border-box;
cursor: pointer;
&:hover {
background-color: #eee;
}
}
}
}
/deep/ .el-input-group {
width: 371px;
}
}
}
</style>
按地名搜索
选中并标注
也可以在地图上点中进行标注
网友评论