Skip to content

OpenLayers 自定义地图样式

上次更新 2025年8月20日星期三 3:16:20 字数 0 字 时长 0 分钟

本章将介绍如何在 OpenLayers 中自定义地图样式。

示例

新标签页预览

代码实现

vue
<template>
  <div class="h-screen">
    <div id="map" class="w-full h-full"></div>
  </div>
</template>

<script setup>
import { onMounted, ref } from "vue";
import "ol/ol.css";
import Map from "ol/Map";
import View from "ol/View";
import TileLayer from "ol/layer/Tile";
import XYZ from "ol/source/XYZ";
import { fromLonLat } from "ol/proj";
import { Vector as VectorLayer } from "ol/layer";
import { Vector as VectorSource } from "ol/source";
import GeoJSON from "ol/format/GeoJSON";
import { Style, Fill, Stroke } from "ol/style";
import Overlay from "ol/Overlay";

onMounted(() => {
  // 初始化地图
  const map = new Map({
    target: "map",
    view: new View({
      center: fromLonLat([104.1954, 35.8617]),
      zoom: 4,
    }),
  });

  // 添加天地图底图
  const tdtLayer = new TileLayer({
    source: new XYZ({
      url: "http://t{0-7}.tianditu.gov.cn/vec_w/wmts?layer=vec&style=default&tilematrixset=w&Service=WMTS&Request=GetTile&Version=1.0.0&Format=tiles&TileMatrix={z}&TileCol={x}&TileRow={y}&tk=d32c6748c80f81a44acd8633cea41dfd",
    }),
  });
  map.addLayer(tdtLayer);

  // 生成随机颜色函数
  function getRandomColor() {
    const colors = [
      "#c12e34",
      "#e6b600",
      "#0098d9",
      "#2b821d",
      "#005eaa",
      "#339ca8",
      "#cda819",
      "#32a487",
    ];
    return colors[Math.floor(Math.random() * colors.length)];
  }

  // 加载中国行政区划GeoJSON数据
  fetch("https://geo.datav.aliyun.com/areas_v3/bound/geojson?code=100000_full")
    .then((response) => response.json())
    .then((data) => {
      // 创建矢量图层
      const vectorSource = new VectorSource({
        features: new GeoJSON().readFeatures(data, {
          featureProjection: "EPSG:3857",
        }),
      });

      const vectorLayer = new VectorLayer({
        source: vectorSource,
        style: function (feature) {
          return new Style({
            fill: new Fill({
              color: getRandomColor() + "99", // 添加透明度
            }),
            stroke: new Stroke({
              color: "#3498db",
              width: 0,
            }),
          });
        },
      });

      map.addLayer(vectorLayer);

      // 添加鼠标交互
      const overlay = new Overlay({
        element: document.createElement("div"),
        positioning: "bottom-center",
        offset: [0, -10],
      });
      map.addOverlay(overlay);

      // map.on("pointermove", function (evt) {
      //   const feature = map.forEachFeatureAtPixel(
      //     evt.pixel,
      //     function (feature) {
      //       return feature;
      //     }
      //   );

      //   if (feature) {
      //     map.getTargetElement().style.cursor = "pointer";

      //     // 高亮显示
      //     feature.setStyle(
      //       new Style({
      //         fill: new Fill({
      //           color: "#e6f7ffee",
      //         }),
      //         stroke: new Stroke({
      //           color: "#1890ff",
      //           width: 0,
      //         }),
      //       })
      //     );

      //     // 显示省份名称
      //     const element = overlay.getElement();
      //     element.innerHTML = feature.getProperties().name;
      //     element.className = "province-label";
      //     overlay.setPosition(evt.coordinate);
      //   } else {
      //     map.getTargetElement().style.cursor = "";
      //     vectorLayer
      //       .getSource()
      //       .getFeatures()
      //       .forEach((f) => {
      //         f.setStyle(null); // 恢复默认样式
      //       });
      //     overlay.setPosition(undefined);
      //   }
      // });
    });
});
</script>

<style scoped>
.h-screen {
  height: 24rem;
}

.w-full {
  width: 100%;
}

.h-full {
  height: 100%;
}

.province-label {
  background: transparent;
  border: none;
  box-shadow: none;
  font-size: 14px;
  font-weight: bold;
  color: #333;
  text-shadow: 2px 2px 3px rgba(255, 255, 255, 0.8);
}
</style>
关注公众号