You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue-Leaflet(Leaflet)如何重置上一个点击国家的样式?

解决Leaflet地图点击新国家时重置上一个选中国家样式的问题

看起来你已经搭好了基础的地图交互框架,但核心问题在于你只记录了选中国家的名称,没有保存对应的图层引用,导致找不到上一个选中的图层来重置它的样式。下面是具体的修复方案:

核心思路

  • 把data里的clicked字段改成保存选中的图层对象(而非国家名称),这样就能直接对它调用setStyle方法重置样式
  • 每次点击新国家时,先检查是否有已选中的图层,若有则重置其样式,再设置当前图层的选中样式
  • 调整鼠标悬停/移出的判断逻辑,基于图层对象而非名称来判断是否是已选中状态

修改后的完整代码

<template>
  <div class="map-wrap">
    <l-map
      ref="map"
      :options="mapOptions"
      :zoom="zoom"
      :minZoom="2.5"
      :zoomAnimation="true"
      :panInsideBounds="true"
      :maxBounds="[
        [90, 180],
        [-90, -180],
      ]"
      :maxBoundsViscosity="1.0"
      :maxZoom="2.4"
      :center="[47.41322, -1.219482]"
    >
      <l-tile-layer
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        layer-type="base"
        name="OpenStreetMap"
      ></l-tile-layer>

      <l-geo-json
        :visible="true"
        :geojson="geojson"
        :options="geojsonOpts"
        ref="arearef"
      />
    </l-map>
  </div>
</template>

<script>
import "leaflet";

import {
  LMap,
  LTileLayer,
  LMarker,
  LPolygon,
  LGeoJson,
} from "@vue-leaflet/vue-leaflet";

// 提取默认样式为常量,避免重复代码
const DEFAULT_STYLE = {
  weight: 1,
  color: "#999",
  dashArray: "",
  fillOpacity: 0.1,
};

// 选中样式常量
const ACTIVE_STYLE = {
  weight: 1,
  color: "#0f0",
  dashArray: "",
  fillOpacity: 0.1,
};

export default {
  components: {
    LMap,
    LTileLayer,
    LMarker,
    LPolygon,
    LGeoJson,
  },
  data() {
    return {
      zoom: 2,
      geojson: null,
      mapOptions: {
        zoomSnap: 0.5,
        preferCanvas: true,
      },
      // 改为保存选中的图层对象,而不是名称
      activeLayer: null,
    };
  },
  async created() {
    const response = await fetch("/dataset/countries.geojson");
    this.geojson = await response.json();
  },
  computed: {
    geojsonOpts() {
      return {
        onEachFeature: (feature, layer) => {
          // 初始化图层样式
          layer.setStyle(DEFAULT_STYLE);
          const countryName = feature.properties.NAME;

          layer.on("click", () => {
            // 如果点击的是已选中的图层,取消选中
            if (this.activeLayer === layer) {
              layer.setStyle(DEFAULT_STYLE);
              this.activeLayer = null;
              return;
            }

            // 重置上一个选中的图层样式
            if (this.activeLayer) {
              this.activeLayer.setStyle(DEFAULT_STYLE);
            }

            // 设置当前图层为选中状态
            layer.setStyle(ACTIVE_STYLE);
            this.activeLayer = layer;
          });

          layer.on("mouseover", () => {
            // 已选中的图层不响应悬停
            if (this.activeLayer === layer) return;
            layer.setStyle(ACTIVE_STYLE);
          });

          layer.on("mouseout", () => {
            // 已选中的图层不响应移出
            if (this.activeLayer === layer) return;
            layer.setStyle(DEFAULT_STYLE);
          });
        },
      };
    },
  },
};
</script>

<style scoped>
.map-wrap {
  width: 100vw;
  height: 100vh;
  margin: 0;
  padding: 0;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  position: absolute;
}
</style>

关键修改点说明

  1. 提取样式常量:把重复的默认样式和选中样式抽成常量,让代码更简洁易维护
  2. 修改状态存储:将clicked改为activeLayer,直接保存选中的Leaflet图层对象,这样就能直接调用setStyle方法
  3. 点击事件逻辑优化:
    • 先判断是否点击的是已选中图层,若是则取消选中并重置样式
    • 若存在上一个选中图层,先重置它的样式
    • 再设置当前图层为选中状态并更新activeLayer
  4. 悬停/移出逻辑简化:直接通过图层对象是否等于activeLayer来判断是否跳过样式修改,无需再依赖国家名称

这样修改后,就能完美实现「点击新国家时自动重置上一个选中国家样式」的需求了。

内容的提问来源于stack exchange,提问作者mosf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 16:30:34