2014-02-10 87 views
0

嘿我試圖在我的MeteorJS項目中使用谷歌地圖,谷歌地圖顯示在地圖上的所有客戶,然後顯示一個信息窗口,當你點擊其中一個標記。谷歌地圖infoWindow點擊事件重新渲染地圖畫布在流星

問題在於,無論何時單擊標記,它都會重新渲染地圖,我知道這與在單擊infoWindow時設置的Session變量的反應性有關。

有什麼辦法避免地圖在會話變量更改時被重新渲染?

謝謝。

下面是JS和模板即時通訊在我的項目中使用。

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

製作Google地圖和標記的代碼。

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"); 
    }; 

}); 

}); 

}; 

信息窗口模板

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

和信息窗口模板

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

回答

0

這是一個有點困難,而不必在我面前的一個運行的版本,可以肯定的JS,但我認爲這主要是因爲你將所有的代碼放在一個大的Deps.autorun塊中。點擊其中一個標記是改變會話變量customerId,這將導致customers_infoWindow重新呈現(因爲它顯然是一個依賴),但我相信這是預期的行爲。

但是,因爲你是在爲你Deps.autorun塊聲明var infoWindow有該模板的一個實例,作爲它的一個屬性,我認爲改變customers_infoWindow實際上將無效整個Deps.autorun計算,這意味着整個塊將被執行再次,包括var map = new google.maps.Map(...)行,這將基本上重新渲染地圖(即使它不重新渲染包含它的實際div元素)。因此,我建議將您的代碼拆分爲單獨的Deps.autorun塊,並確保同一塊中的任何內容應該同時重新運行 - 顯然,這意味着Google Maps初始化代碼和infoWindow處理程序應該在單獨的塊中。

要重申,我認爲這是發生了什麼事情,但你必須嘗試,讓我知道...

+0

我只是試圖將代碼分解爲2個獨立的'Deps'第二個'Deps'不能讀取映射選項,因爲它在第一個Deps塊中定義並且超出了範圍。 – Moshe

+0

如果有一種方法可以使點擊不附加到地圖模板,但是可以避免重新渲染的不同模板 – Moshe

+0

您不能只在Deps塊外面聲明'mapOptions'變量,然後設置它的價值在Deps塊? – richsilv

1

如果你創建一個全局的GoogleMaps對象,你可以從任何地方訪問它的屬性。 This article有一個很好的例子。 總體要點是:

  1. 使用初始化方法創建Google地圖類。在初始化方法結束時,爲你的地圖的存在設置一個會話變量。 (Session.set('map',true);)
  2. 調用通過在Template.customers_map.rendered內調用googlemap init方法來創建googlemap對象。