文字标注
TIP
输入文字后点击地图方可添加文字标注。
代码如下:
点我查看代码
vue
<template>
<el-input
v-model="state.input"
placeholder="输入文字后点击地图方可添加文字标注"
clearable
style="margin-bottom: 20px"
/>
<div id="map"></div>
</template>
<script lang="ts" setup>
import { onMounted, reactive, onBeforeUnmount } from "vue";
import { Map, View, Feature } from "ol";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { defaults, FullScreen } from "ol/control";
import { XYZ, Vector as VectorSource } from "ol/source";
import { Point } from "ol/geom";
import { ElMessage } from "element-plus";
import { createLabelStyle, addVectorLabel } from "./tools";
import { ATTRIBUTIONS, SHENZHEN, MAPURL } from "../../../constants";
interface State {
input: string;
map: Map | null;
vectorSource: VectorSource<Point> | null;
}
const state: State = reactive({
input: "",
map: null,
vectorSource: null,
});
const raster = new TileLayer({
source: new XYZ({
attributions: ATTRIBUTIONS,
url: MAPURL,
maxZoom: 20,
}),
});
const initMap = () => {
state.map = new Map({
//初始化map
target: "map",
//地图容器中加载的图层
layers: [
//加载瓦片图层数据
raster,
],
view: new View({
projection: "EPSG:4326", // 坐标系,有EPSG:4326和EPSG:3 857
center: SHENZHEN, // 深圳坐标
//地图初始显示级别
zoom: 5,
}),
//加载控件到地图容器中
controls: defaults().extend([
new FullScreen(), //加载全屏显示控件(目前支持非IE内核浏览器)
]),
});
//实例化Vector要素,通过矢量图层添加到地图容器中
const iconFeature = new Feature({
geometry: new Point(SHENZHEN),
//名称属性
name: "深圳市",
});
iconFeature.setStyle(createLabelStyle(iconFeature));
//矢量标注的数据源
state.vectorSource = new VectorSource({
features: [iconFeature],
});
//矢量标注图层
const vectorLayer = new VectorLayer({
source: state.vectorSource,
});
state.map.addLayer(vectorLayer);
};
onMounted(() => {
initMap();
if (state.map) {
state.map.on("click", (evt) => {
if (!state.input) {
ElMessage({
message: "请先添加标注名",
type: "warning",
});
return;
}
//鼠标单击点坐标
const coordinate = evt.coordinate;
//添加一个新的标注(矢量要素)
addVectorLabel({
coordinate,
vectorSource: state.vectorSource,
name: state.input,
});
});
}
});
onBeforeUnmount(() => {
if (state.map) {
state.map.dispose();
state.map = null;
}
});
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
#map {
height: 650px;
}
</style>
tools 代码如下:
点我查看代码
ts
import { Style, Text, Fill, Stroke } from 'ol/style'
import { Feature } from 'ol'
import { FeatureLike } from 'ol/Feature'
import { Point } from 'ol/geom'
import { VectorLabelOptions } from '../../../@types'
/**
* 创建矢量标注样式函数,设置image为图标ol.style.Icon
* @param {ol.Feature} feature 要素
*/
export const createLabelStyle = (feature: FeatureLike): Style =>
new Style({
text: new Text({
//位置
textAlign: 'center',
//基准线
textBaseline: 'middle',
//文字样式
font: 'normal 14px 微软雅黑',
//文本内容
text: feature.get('name'),
//文本填充样式(即文字颜色)
fill: new Fill({ color: '#aa3300' }),
stroke: new Stroke({ color: '#ffcc33', width: 2 }),
}),
})
/**
* 添加一个新的标注(矢量要素)
* @param {ol.Coordinate} coordinate 坐标点
* @param {ol.source.Vector} vectorSource 矢量标注的数据源
* @param {String} name 标注名
*/
export const addVectorLabel = ({
coordinate,
vectorSource,
name = '标注点',
}: VectorLabelOptions) => {
if (vectorSource === null) return
//新建一个要素 ol.Feature
const newFeature = new Feature({
//几何信息
geometry: new Point(coordinate),
//名称属性
name,
})
//设置要素的样式
newFeature.setStyle(createLabelStyle(newFeature))
//将新要素添加到数据源中
vectorSource.addFeature(newFeature)
}