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

点击自定义图例列表项时Popup与图层样式不显示的修复请求

问题描述

点击自定义图例列表项时,Popup弹窗与图层样式无法正常显示,但直接点击美国州图层时功能完全正常。两者调用同一代码逻辑,却呈现不同运行效果,该如何修复?

效果对比

  • 点击州图层正常效果:
    点击州图层正常效果
  • 点击图例项仅缩放生效效果:
    点击图例项仅缩放生效效果

地图组件代码

import Component from "@ember/component";
import { createPopupContent } from "../common/utils";

export default Component.extend({
  classNames: ["map"],
  geoJson: null,
  map: null,
  activeState: "",
  _prevState: "",

  init() {
    this._super(...arguments);
    this.set("zoom", layer => {
      layer.setStyle({
        weight: 5,
        color: "#C97064",
        dashArray: "15",
        fillOpacity: 0.7
      });
      layer.bringToFront();
      layer.bindPopup(createPopupContent(layer.feature.properties)).openPopup();
      this.set("activeState", layer.feature.properties.name);
      this.get("map").fitBounds(layer.getBounds());
    });
  },

  didRender() {
    if (document.querySelector(".active")) {
      document.querySelector(".active").scrollIntoView({
        block: "start"
      });
    }
  },

  didInsertElement() {
    this._super(...arguments);
    this.set("map", L.map(this.element).setView([37.8, -96], 4));

    L.tileLayer(
      "https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png",
      {
        maxZoom: 19
      }
    ).addTo(this.get("map"));

    function zoomToFeature(e) {
      this.get("zoom")(e.target);
    }

    function onPopupClose(e) {
      const layer = e.target;
      this.set("activeState", "");

      this.get("geoJson").resetStyle(layer);
    }

    function _onEachFeature(feature, layer) {
      layer.on({
        click: zoomToFeature.bind(this),
        popupclose: onPopupClose.bind(this)
      });
    }
    this.set(
      "geoJson",
      L.geoJson(this.get("data").toArray(), {
        onEachFeature: _onEachFeature.bind(this)
      }).addTo(this.get("map"))
    );
  },

  actions: {
    setActiveState(state) {
      this.set("activeState", state);
      this.get("map").eachLayer(
        function(layer) {
          if (
            layer.feature &&
            layer.feature.properties.name === this.get("activeState")
          ) {
            this.get("zoom")(layer);
          }
        }.bind(this)
      );
    }
  }
});
修复方案

核心问题是图层遍历对象错误:原代码用map.eachLayer()遍历地图顶层图层,而州图层被包含在geoJson这个GeoJSON组图层内,无法直接访问到单个州的子图层,导致样式和Popup逻辑无法触发。同时补充重置旧图层样式、避免重复绑定Popup的优化。

1. 修改图例点击的图层遍历逻辑

替换actions中的setActiveState方法:

actions: {
  setActiveState(state) {
    // 重置上一个激活州的样式
    if (this.get('_prevState')) {
      this.get('geoJson').eachLayer(layer => {
        if (layer.feature?.properties.name === this.get('_prevState')) {
          this.get('geoJson').resetStyle(layer);
        }
      });
    }
    this.set('_prevState', state);
    
    // 遍历GeoJSON组内的子图层(单个州)
    this.get('geoJson').eachLayer(
      function(layer) {
        if (
          layer.feature &&
          layer.feature.properties.name === state
        ) {
          this.get('zoom')(layer);
        }
      }.bind(this)
    );
  }
}

2. 优化zoom方法避免重复绑定Popup

修改init中的zoom函数:

this.set("zoom", layer => {
  layer.setStyle({
    weight: 5,
    color: "#C97064",
    dashArray: "15",
    fillOpacity: 0.7
  });
  layer.bringToFront();
  // 仅在图层无Popup时绑定,避免重复创建
  if (!layer.getPopup()) {
    layer.bindPopup(createPopupContent(layer.feature.properties));
  }
  layer.openPopup();
  this.set("activeState", layer.feature.properties.name);
  this.get("map").fitBounds(layer.getBounds());
});

修复说明

  • 遍历对象修正:用geoJson.eachLayer()直接访问组内的单个州图层,确保能找到目标图层并触发样式和Popup逻辑。
  • 旧样式重置:通过_prevState记录上一个激活的州,避免多个州同时显示激活样式。
  • Popup优化:避免重复绑定Popup,减少DOM操作冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 14:25:19