openlayers绘制图标并定位到图标
环境
vue3
ts
sass
具体代码
<template>
<div class="btn-wrapper">
<span style="color: red"> 上一个定位的点 {{ prePoint }}</span>
<button
class="button"
v-for="(item, index) in data"
:key="index"
@click="handleMoveToTarget(item)"
>
定位到目标 item
</button>
</div>
<div id="map" class="map"></div>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import 'ol/ol.css'
import { Map, View, Feature } from 'ol'
import { XYZ, Vector as SourceVector } from 'ol/source'
import TileLayer from 'ol/layer/Tile'
import { Vector as LayerVector } from 'ol/layer'
import { Style, Icon, Text, Fill, Stroke } from 'ol/style'
import { Point } from 'ol/geom'
const data = [
[158.6, 29.8],
[159, 30.5],
[159.4, 30.9],
[160.2, 31.8],
[160.5, 32.2],
[162.4, 33.4],
[164, 34.3],
[166.2, 35.7],
[167.6, 36.3]
]
const map = ref<Map>()
const prePoint = ref<number[]>([])
const customLayer = new LayerVector({
source: new SourceVector()
})
const setItem = (point: number[], color = '#000') => {
const anchor = new Feature({
name: `[${point}]`,
geometry: new Point(point)
})
// 设置样式,在样式中就可以设置图标
anchor.setStyle(
new Style({
image: new Icon({
src: '/logo.png',
width: 60,
height: 60,
color: color
}),
text: new Text({
textAlign: 'center', // 位置
textBaseline: 'middle', // 基准线
font: 'normal 12px 微软雅黑', // 文字样式
text: anchor.get('name'),
// text: '文字样式',
fill: new Fill({
// 文本填充样式(即文字颜色)
color: '#fff'
}),
stroke: new Stroke({
color: '#999',
width: 1
})
}),
stroke: new Stroke({
color: '#fff',
width: 100
})
})
)
// 添加点击事件
;(anchor.on as any)('click', (e: any) => {
console.log(e, 'e')
})
customLayer.getSource()?.addFeature(anchor)
}
const init = () => {
map.value = new Map({
target: 'map',
layers: [
new TileLayer({
source: new XYZ({
url: 'http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}',
wrapX: false
})
}),
customLayer
],
view: new View({
projection: 'EPSG:4326',
// 定位
// center: [110.592595, 20.911173],
center: [158.6, 29.8],
zoom: 8,
maxZoom: 18,
minZoom: 1
})
})
data.forEach((item) => {
setItem(item)
})
map.value?.on('click', function (this: any, e) {
console.log(e.pixel)
console.log(this)
this.forEachFeatureAtPixel(e.pixel, function (feature: any) {
// 为点击的feature发送自定义的click消息
feature.dispatchEvent && feature.dispatchEvent({ type: 'click', event: e })
})
})
}
// 定位到目标
const handleMoveToTarget = (point: number[]) => {
// 还原原来的颜色
if (prePoint.value.length) {
setItem(prePoint.value)
}
let zoom = map.value?.getView().getZoom() as number
const duration = 2000
map.value?.getView().animate(
{
center: point,
duration: duration
},
(e) => {
console.log(e, 'callback-1')
}
)
map.value?.getView().animate(
{
zoom: zoom - 1,
duration: duration / 2
},
{
zoom: zoom,
duration: duration / 2
},
(e) => {
console.log(e, 'callback-2')
setItem(point, '#0f0')
prePoint.value = point
}
)
}
onMounted(init)
</script>
<style lang="scss">
.map {
height: 100vh;
width: 100%;
background-color: #000;
}
.btn-wrapper {
width: 100%;
position: fixed;
left: 150px;
top: 30px;
z-index: 2;
.button + .button {
margin-left: 20px;
}
}
</style>