Skip to content

文字标注

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)
}

如有转载或 CV 的请标注本站原文地址