【问题标题】:google maps infoWindow click event re-renders map-canvas in Meteor谷歌地图 infoWindow 点击事件在 Meteor 中重新渲染地图画布
【发布时间】:2014-02-10 23:02:10
【问题描述】:

嘿,我正在尝试在我的 MeteorJS 项目中使用谷歌地图,以便在所有客户的地图上显示谷歌地图,然后在您单击其中一个标记时显示一个 infoWindow。

问题是任何时候你点击它都会从头开始重新渲染地图的标记,我知道这与点击 infoWindow 时设置的 Session 变量的反应性有关。

有什么办法可以避免在会话变量发生变化时重新渲染地图?

谢谢。

下面是我项目中使用的 JS 和模板。

 <template name="customers_map">
 {{#constant}}
 <div id="mapWrapper">
    <div id="map-canvas"></div>
 </div>
 {{/constant}}
</template>

制作谷歌地图和标记的代码。

Template.customers_map.rendered = function() {

$("#map-canvas").height("400px");

if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function(p) {
        Session.set("myLat", p.coords.latitude);
        Session.set("myLng", p.coords.longitude);
    });
}

Deps.autorun(function(){

    var mapOptions = {
        center: new google.maps.LatLng(Session.get("myLat"), Session.get("myLng")),
        zoom: 15,
        zoomControl: true,
        zoomControlOptions: {style: google.maps.ZoomControlStyle.SMALL},
        streetViewControl: false,
        mapTypeControl: false,
        scaleControl: true,
        mapTypeId: google.maps.MapTypeId.SMALL
    }

var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);

var infowindow = new google.maps.InfoWindow({
  content: Template.customers_infoWindow()
  });

Customers.find().forEach(function(customer) {

    if (customer.loc != null) {
        var geo = customer.geoLocation();
        var marker = new google.maps.Marker({
            position: new google.maps.LatLng(geo.lat, geo.lng),
            title: customer.name(),
            icon:'http://maps.google.com/mapfiles/ms/icons/green-dot.png'
        });

        marker.setMap(map);

        google.maps.event.addListener(marker, 'click', function() {
            Session.set("customerId", customer._id);
            infowindow.open(map,marker);
        });

    } else {
        console.log(customer.name() + " has no geoLocation");
    };

});

});

};

infoWindow 模板

<template name="customers_infoWindow">
    <h1>{{record.name}}</h1>
</template>

以及 infoWindow 模板的 js

Template.customers_infoWindow.record = function() {
  return Customers.findOne({_id: Session.get("customerId")});
}

【问题讨论】:

    标签: google-maps-api-3 meteor


    【解决方案1】:

    如果您创建一个全局 googlemaps 对象,您可以从任何地方访问它的属性。 This article 有一个很好的例子。 总体要点是:

    1. 使用初始化方法创建一个 googlemaps 类。在初始化方法结束时,为您的地图的存在设置一个会话变量。 ( Session.set('map', true);)
    2. 通过从 Template.customers_map.rendered 中调用 googlemap init 方法来调用创建 googlemap 对象。

    【讨论】:

      【解决方案2】:

      如果我面前没有正在运行的版本,这有点难以确定,但我认为这本质上是因为您将所有代码都放在一个大的 Deps.autorun 块中。单击其中一个标记正在更改 Session 变量 customerId,这将导致 customers_infoWindow 重新呈现(因为它显然是一个依赖项),但我确信这是预期的行为。

      但是,由于您在 Deps.autorun 块中声明 var infoWindow 以将该模板的实例作为其属性之一,我认为更改 customers_infoWindow 实际上会使整个 Deps.autorun 计算无效,这意味着将再次执行整个块,包括 var map = new google.maps.Map(...) 行,这将实质上重新渲染地图(即使它不会重新渲染包含它的实际 div 元素)。

      因此,我建议将您的代码拆分为单独的 Deps.autorun 块,并确保同一块中的任何内容都应同时重新运行 - 显然,这意味着 Google 地图初始化代码和 @ 987654330@ 处理程序应位于单独的块中。

      重申一下,我认为就是这样,但您必须尝试一下并告诉我...

      【讨论】:

      • 我只是尝试将代码分成 2 个单独的 Deps 第二个 Deps 无法读取 map 选项,因为它在第一个 Deps 块中定义并且超出范围。
      • 如果有办法使点击不附加到地图模板而是附加到可以避免重新渲染的不同模板
      • 你不能直接在 Deps 块之外声明mapOptions 变量,然后在 Deps 块中设置它的值吗?
      猜你喜欢
      • 1970-01-01
      • 2011-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-03
      • 2020-04-25
      • 1970-01-01
      • 2015-06-06
      相关资源
      最近更新 更多