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

求助:Search Box无法关联Google Map的问题

问题:Google Map Search Box组件无法与地图关联

尝试给Google Map添加Search Box组件,但组件无法和地图正常关联,以下是我的实现代码:

JavaScript代码

$(document).ready(function() {
  initMap();
});

$(document).on('change', '#search', function() {
  var id = $(this).val();
  initMap(id);
});


function initMap(id = '') {
  if (id == 'volvo') {
    // 指定地图中心及其他配置
    var mapOptions = {
      center: {
        lat: 40.7128,
        lng: -74.0060
      }, // 纽约坐标
      zoom: 12
    };

    // 创建新地图实例
    var map = new google.maps.Map(document.getElementById('map'), mapOptions);

    // 指定圆形覆盖物的中心和半径
    var circleOptions = {
      strokeColor: '#FF0000',
      strokeOpacity: 0.8,
      strokeWeight: 2,
      fillColor: '#FF0000',
      fillOpacity: 0.35,
      map: map,
      center: {
        lat: 40.7128,
        lng: -74.0060
      },
      radius: 10000 // 半径(米)
    };

    // 创建圆形覆盖物
    var circle = new google.maps.Circle(circleOptions);
  } else {

    // 指定地图中心及其他配置
    var mapOptions = {
      center: {
        lat: 51.5072,
        lng: 0.1276
      }, // 伦敦坐标
      zoom: 12
    };

    // 创建新地图实例
    var map = new google.maps.Map(document.getElementById('map'), mapOptions);

    // 指定圆形覆盖物的中心和半径
    var circleOptions = {
      strokeColor: '#FF0000',
      strokeOpacity: 0.8,
      strokeWeight: 2,
      fillColor: '#FF0000',
      fillOpacity: 0.35,
      map: map,
      center: {
        lat: 51.5072,
        lng: 0.1276
      },
      radius: 10000 // 半径(米)
    };

    // 创建圆形覆盖物
    var circle = new google.maps.Circle(circleOptions);

  }

  // 创建搜索框并关联UI元素
  const input = document.getElementById("pac-input");
  const searchBox = new google.maps.places.SearchBox(input);

  map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
  // 让搜索结果偏向当前地图视口
  map.addListener("bounds_changed", () => {
    searchBox.setBounds(map.getBounds());
  });

  let markers = [];

  // 监听用户选择搜索结果的事件,获取地点详情
  searchBox.addListener("places_changed", () => {
    const places = searchBox.getPlaces();

    if (places.length == 0) {
      return;
    }

    // 清除旧标记
    markers.forEach((marker) => {
      marker.setMap(null);
    });
    markers = [];

    // 遍历每个地点,获取图标、名称和位置
    const bounds = new google.maps.LatLngBounds();

    places.forEach((place) => {
      if (!place.geometry || !place.geometry.location) {
        console.log("返回的地点没有几何信息");
        return;
      }

      const icon = {
        url: place.icon,
        size: new google.maps.Size(71, 71),
        origin: new google.maps.Point(0, 0),
        anchor: new google.maps.Point(17, 34),
        scaledSize: new google.maps.Size(25, 25),
      };

      // 为每个地点创建标记
      markers.push(
        new google.maps.Marker({
          map,
          icon,
          title: place.name,
          position: place.geometry.location,
        }),
      );
      if (place.geometry.viewport) {
        // 仅地理编码结果有视口
        bounds.union(place.geometry.viewport);
      } else {
        bounds.extend(place.geometry.location);
      }
    });
    map.fitBounds(bounds);
  });
}

HTML代码

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=APIKey&libraries=places" defer></script>

<input id="pac-input" class="controls" type="text" placeholder="Search Box">
<div id="map" style="height: 400px; width: 100%"></div>
<select id="search">
  <option value="volvo">Volvo</option>
  <option value="saab">Saab</option>
  <option value="mercedes">Mercedes</option>
  <option value="audi">Audi</option>
</select>

修复方案

问题根源

  1. 重复初始化冲突:每次下拉框切换都会调用initMap,重新创建地图、SearchBox实例,同时重复将搜索框输入控件添加到地图控件中,导致控件堆叠、事件监听重复绑定,引发关联异常。
  2. 变量作用域隐患:map变量在if/else块内用var声明,虽因变量提升不会直接报错,但旧实例的事件监听未被清理,新地图无法正确关联SearchBox。

修复后的代码

JavaScript

// 全局维护核心实例,避免重复创建
let map, circle, searchBox, markers = [];
const input = document.getElementById("pac-input");

$(document).ready(function() {
  // 初始化地图和SearchBox(仅执行一次)
  initMap();
  initSearchBox();
});

$(document).on('change', '#search', function() {
  var id = $(this).val();
  // 仅更新地图中心和圆形覆盖物,不重建地图
  updateMap(id);
});

// 初始化基础地图
function initMap(id = '') {
  let mapCenter = id == 'volvo' 
    ? { lat: 40.7128, lng: -74.0060 } 
    : { lat: 51.5072, lng: 0.1276 };

  const mapOptions = {
    center: mapCenter,
    zoom: 12
  };

  map = new google.maps.Map(document.getElementById('map'), mapOptions);
  // 创建初始圆形覆盖物
  updateCircle(mapCenter);
}

// 更新地图中心和圆形覆盖物
function updateMap(id) {
  let mapCenter = id == 'volvo' 
    ? { lat: 40.7128, lng: -74.0060 } 
    : { lat: 51.5072, lng: 0.1276 };
  
  // 更新地图中心
  map.setCenter(mapCenter);
  // 更新圆形覆盖物
  updateCircle(mapCenter);
}

// 更新圆形覆盖物实例
function updateCircle(center) {
  // 移除旧的圆形覆盖物
  if (circle) circle.setMap(null);
  
  const circleOptions = {
    strokeColor: '#FF0000',
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: '#FF0000',
    fillOpacity: 0.35,
    map: map,
    center: center,
    radius: 10000
  };
  circle = new google.maps.Circle(circleOptions);
}

// 初始化SearchBox并绑定关联逻辑(仅执行一次)
function initSearchBox() {
  searchBox = new google.maps.places.SearchBox(input);
  // 将搜索框添加到地图控件(仅一次)
  map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);

  // 绑定地图边界变化事件
  map.addListener("bounds_changed", () => {
    searchBox.setBounds(map.getBounds());
  });

  // 绑定搜索结果选择事件
  searchBox.addListener("places_changed", () => {
    const places = searchBox.getPlaces();
    if (places.length == 0) return;

    // 清除旧标记
    markers.forEach(marker => marker.setMap(null));
    markers = [];

    const bounds = new google.maps.LatLngBounds();
    places.forEach(place => {
      if (!place.geometry || !place.geometry.location) {
        console.log("返回的地点没有几何信息");
        return;
      }

      const icon = {
        url: place.icon,
        size: new google.maps.Size(71, 71),
        origin: new google.maps.Point(0, 0),
        anchor: new google.maps.Point(17, 34),
        scaledSize: new google.maps.Size(25, 25),
      };

      markers.push(
        new google.maps.Marker({
          map,
          icon,
          title: place.name,
          position: place.geometry.location,
        })
      );

      if (place.geometry.viewport) {
        bounds.union(place.geometry.viewport);
      } else {
        bounds.extend(place.geometry.location);
      }
    });
    map.fitBounds(bounds);
  });
}

HTML(仅需替换APIKey)

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=你的API密钥&libraries=places" defer></script>

<input id="pac-input" class="controls" type="text" placeholder="Search Box">
<div id="map" style="height: 400px; width: 100%"></div>
<select id="search">
  <option value="volvo">Volvo</option>
  <option value="saab">Saab</option>
  <option value="mercedes">Mercedes</option>
  <option value="audi">Audi</option>
</select>

修复说明

  • 将核心实例(地图、圆形覆盖物、SearchBox)提升到全局作用域,避免重复创建和资源浪费。
  • 拆分逻辑:初始化仅执行一次,下拉切换时仅更新地图中心和圆形覆盖物,不重建整个地图。
  • 清理旧实例:更新圆形覆盖物前先移除旧实例,避免覆盖物堆积;SearchBox仅绑定一次事件,避免冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 13:44:53