2014-02-28 55 views
6

我現在正在構建自定義Knockout.js綁定來處理多邊形的繪製。在這種情況下,Knockout API只給我一個DOM對象的引用來訪問我需要更新的任何東西。但是,它看起來像設計leaflet.js希望用戶將地圖實例存儲在其實現中。我沒有這個選擇。如何僅使用DOM對象獲得leaflet.js實例?

嘗試這給了我一個錯誤:var existingMap = L.map('aMapIDGoesHere')

和錯誤是:map already initialized

任何方式我可以使用DOM元素或元素ID來訪問地圖實例?

通過請求這裏的自定義綁定,請注意這是一項正在進行的工作:

ko.bindingHandlers.leafletDraw = { 
    init: function(element, valueAccessor, allBindingsAccessor) { 
    var map = L.map(element).setView([40, -90], 3); 
    var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { 
     attribution: 'OSM', 
     minZoom: 2 
    }).addTo(map); 

    // Initialise the FeatureGroup to store editable layers 
    var editableLayers = new L.FeatureGroup(); 
    map.addLayer(editableLayers); 

    // Initialise the draw control and pass it the FeatureGroup of editable layers 
    var drawOptions = { 
     edit: { 
     featureGroup: editableLayers, 
     remove: false 
     }, 
     draw: { 
     polyline: false, 
     circle: false, 
     marker: false, 
     polygon: { 
      allowIntersection: false, 
      showArea: true 
     } 
     } 
    } 
    var drawControl = new L.Control.Draw(drawOptions); 
    map.addControl(drawControl); 

    // when a shape is first created 
    map.on('draw:created', function (e) { 
     var shapeString = $.map(e.layer._latlngs, function(pair) { return pair.lng.toString()+"::"+pair.lat.toString(); }).join(";;;"); 
     var value = valueAccessor(); 
     if (ko.isObservable(value)) { 
     value(shapeString); 
     } 

     editableLayers.addLayer(e.layer); 

     drawControl.removeFrom(map); 
     drawOptions.draw.polygon = false; 
     drawOptions.draw.rectangle = false; 
     var editControl = new L.Control.Draw(drawOptions); 
     map.addControl(editControl); 
    }); 

    // handle when a shape is edited 
    map.on('draw:edited', function (e) { 
     var editedLayer = e.layers._layers[Object.keys(e.layers._layers)[0]]; 
     var shapeString = $.map(editedLayer._latlngs, function(pair) { return pair.lng.toString()+"::"+pair.lat.toString(); }).join(";;;"); 
     var value = valueAccessor(); 
     if (ko.isObservable(value)) { 
     value(shapeString); 
     } 
    }); 
    }, 
    update: function(element, valueAccessor) { 
    // need to figure this out since we can't access leaflet params from 
    } 
}; 

特別注意你會發現,我轉換點進去一個連接字符串。這是暫時需要的。

+0

你可以添加你的代碼嗎? –

+0

@ leszek.hanusz完成。代碼重要的部分在底部的'update'屬性下。沒有辦法只使用'element'來獲取地圖實例。 – crockpotveggies

回答

6

只要您確定DOM元素不會被刪除,您可以將其添加爲DOM元素本身的子屬性。下面是使用單張頭版設立單張地圖的代碼綁定的處理程序:

ko.bindingHandlers.leaflet = { 
    init: function(element, valueAccessor){ 
     var map = L.map(element); 
     element.myMapProperty = map; 
     L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { 
      attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' 
     }).addTo(map); 
    }, 
    update: function(element, valueAccessor){ 
     var existingMap = element.myMapProperty; 
     var value = ko.unwrap(valueAccessor()); 
     var latitude = ko.unwrap(value.latitude); 
     var longitude = ko.unwrap(value.longitude); 
     var zoom = ko.unwrap(value.zoom); 
     existingMap.setView([latitude, longitude], zoom); 
    } 
}; 

要使用綁定的處理程序,你會只綁定如下所示:

<div data-bind="leaflet: { latitude: latitudeProperty, longitude: longitudeProperty, zoom: zoomProperty }"></div> 

只要確保你還設計了div以確保它具有高度和寬度。我寫了a jsfiddle which uses the above leaflet bindingHandler你可以試試看。

我只在Internet Explorer 11,Firefox 26.0和Firefox 27.0.1上測試過這個jsfiddle。

+0

哇,從來沒有想過實際存儲它在DOM對象本身。思路不錯:)在我的用例中,如果DOM對象被移除,那麼沒有理由進一步訪問它。感謝你! – crockpotveggies

+0

您可能希望查看'ko.utils.domNodeDisposal.addDisposeCallback',以確保在DOM對象被移除時處置地圖對象和事件偵聽器。類似於'ko.utils.domNodeDisposal.addDisposeCallback(element,function(){element.myMapProperty.remove();});'或類似的應該可以很好地工作。 (請注意,此評論中的代碼完全未經測試。) –