如何使用knocklet.js与leaflet.js地图标记?

时间:2014-07-16 06:35:53

标签: javascript asp.net-mvc html5 knockout.js leaflet

我们正在为位于不同地点的工业工厂构建网络可视化。目前,我们在概述页面中使用表格布局。每行代表一个工厂及其最重要的状态和价值。

现在需要另外显示带有标记的地图。每个标记的颜色应代表当前状态(绿色= ok,红色=错误,黄色=警告等)。

在我们当前基于表的页面中,我们使用knockout.js将各个工厂属性从viewmodel绑定到表行(以及其中的相应div等)。只要状态或值发生变化,viewmodel的值就会通过signalr更新,因此您可以将其视为工厂状态的实时,基于事件的表示。

由于这个视图模型已经包含了我们需要在地图上显示的所有信息,我想将传单标记绑定到视图模型,但我看不出如何做到这一点的方法。问题是我没有可以使用data-bind属性的标记元素。

准确地说:我可以为每个工厂添加(静态)标记,这不是问题,但是我无法将它们数据绑定到viewmodel,以便动态地表示viewmodel中的变化值。有办法吗?

我真的很想继续传单,因为它完全符合我们的需求。 Web应用程序需要在永久断开连接到互联网的特殊网络中运行,因此我们需要提供自己的磁贴(适用于传单和Maperetive)。如果除了传单之外还有其他解决方案可以满足我们的需求,请告诉我。谢谢!

更新:这是我的viewmodel的实际json数据。每行代表一个站。每个电台的纬度/经度尚未添加,但我猜这个问题可以忽略不计。

{
   "Rows":[
      {
         "StationId":1,
         "Text":"MCU SE (SE 1/1) DAE",
         "IsDialInStation":false,
         "ConnectState":{
            "StationId":1,
            "DpId":14,
            "Name":null,
            "Value":1,
            "TimeStamp":"\/Date(1400149092000)\/"
         },
         "ConnectStateText":"Nicht verbunden. Hier klicken für Anwahl!",
         "HasActualData":{
            "StationId":1,
            "DpId":10,
            "Name":null,
            "Value":1,
            "TimeStamp":"\/Date(1404890137000)\/"
         },
         "Anlage":{
            "StationId":1,
            "DpId":20101,
            "Name":"Anlage",
            "Value":1,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "cmdSchalteAnlage":{
            "StationId":1,
            "DpId":20013,
            "Name":"cmdAnlage",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Kurzzeit":{
            "StationId":1,
            "DpId":20104,
            "Name":"Kurzzeit",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "cmdSchalteKurzzeit":{
            "StationId":1,
            "DpId":20012,
            "Name":"cmdKurzzeit",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Handbetrieb":{
            "StationId":1,
            "DpId":20160,
            "Name":"Handbetrieb",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Betriebsbereit":{
            "StationId":1,
            "DpId":20121,
            "Name":"Betriebsbereit",
            "Value":1,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Heizt":{
            "StationId":1,
            "DpId":20451,
            "Name":"Heizt",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Sammelstoerung":{
            "StationId":1,
            "DpId":20140,
            "Name":"Sammelstoerung",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "SammelstoerungTechnisch":{
            "StationId":1,
            "DpId":20129,
            "Name":"SammelstoerungTechnisch",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "KommunikationsStoerung":{
            "StationId":1,
            "DpId":20138,
            "Name":"KommunikationsStoerung",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "KommunikationsStoerungKE":{
            "StationId":1,
            "DpId":20137,
            "Name":"KommunikationsStoerungKE",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "AllowCommands":true,
         "AllowParameters":true
      },
      {
         "StationId":2,
         "Text":"MCU SE (SE 2/1) Turm",
         "IsDialInStation":false,
         "ConnectState":{
            "StationId":2,
            "DpId":14,
            "Name":null,
            "Value":1,
            "TimeStamp":"\/Date(1402984603000)\/"
         },
         "ConnectStateText":"Nicht verbunden. Hier klicken für Anwahl!",
         "HasActualData":{
            "StationId":2,
            "DpId":10,
            "Name":null,
            "Value":1,
            "TimeStamp":"\/Date(1404890136000)\/"
         },
         "Anlage":{
            "StationId":2,
            "DpId":20101,
            "Name":"Anlage",
            "Value":1,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "cmdSchalteAnlage":{
            "StationId":2,
            "DpId":20013,
            "Name":"cmdAnlage",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Kurzzeit":{
            "StationId":2,
            "DpId":20104,
            "Name":"Kurzzeit",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "cmdSchalteKurzzeit":{
            "StationId":2,
            "DpId":20012,
            "Name":"cmdKurzzeit",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Handbetrieb":{
            "StationId":2,
            "DpId":20160,
            "Name":"Handbetrieb",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Betriebsbereit":{
            "StationId":2,
            "DpId":20121,
            "Name":"Betriebsbereit",
            "Value":1,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Heizt":{
            "StationId":2,
            "DpId":20451,
            "Name":"Heizt",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Sammelstoerung":{
            "StationId":2,
            "DpId":20140,
            "Name":"Sammelstoerung",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "SammelstoerungTechnisch":{
            "StationId":2,
            "DpId":20129,
            "Name":"SammelstoerungTechnisch",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "KommunikationsStoerung":{
            "StationId":2,
            "DpId":20138,
            "Name":"KommunikationsStoerung",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "KommunikationsStoerungKE":{
            "StationId":2,
            "DpId":20137,
            "Name":"KommunikationsStoerungKE",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "AllowCommands":true,
         "AllowParameters":true
      },
      {
         "StationId":4,
         "Text":"Test W 1",
         "IsDialInStation":false,
         "ConnectState":{
            "StationId":4,
            "DpId":14,
            "Name":null,
            "Value":1,
            "TimeStamp":"\/Date(1402996083000)\/"
         },
         "ConnectStateText":"Nicht verbunden. Hier klicken für Anwahl!",
         "HasActualData":{
            "StationId":4,
            "DpId":10,
            "Name":null,
            "Value":0,
            "TimeStamp":"\/Date(1404890134000)\/"
         },
         "Anlage":{
            "StationId":4,
            "DpId":20101,
            "Name":"Anlage",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "cmdSchalteAnlage":{
            "StationId":4,
            "DpId":20013,
            "Name":"cmdAnlage",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Kurzzeit":{
            "StationId":4,
            "DpId":20104,
            "Name":"Kurzzeit",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "cmdSchalteKurzzeit":{
            "StationId":4,
            "DpId":20012,
            "Name":"cmdKurzzeit",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Handbetrieb":{
            "StationId":4,
            "DpId":20160,
            "Name":"Handbetrieb",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Betriebsbereit":{
            "StationId":4,
            "DpId":20121,
            "Name":"Betriebsbereit",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Heizt":{
            "StationId":4,
            "DpId":20451,
            "Name":"Heizt",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Sammelstoerung":{
            "StationId":4,
            "DpId":20140,
            "Name":"Sammelstoerung",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "SammelstoerungTechnisch":{
            "StationId":4,
            "DpId":20129,
            "Name":"SammelstoerungTechnisch",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "KommunikationsStoerung":{
            "StationId":4,
            "DpId":20138,
            "Name":"KommunikationsStoerung",
            "Value":1,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "KommunikationsStoerungKE":{
            "StationId":4,
            "DpId":20137,
            "Name":"KommunikationsStoerungKE",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "AllowCommands":true,
         "AllowParameters":true
      },
      {
         "StationId":3,
         "Text":"Test W 2",
         "IsDialInStation":false,
         "ConnectState":{
            "StationId":3,
            "DpId":14,
            "Name":null,
            "Value":1,
            "TimeStamp":"\/Date(1402996031000)\/"
         },
         "ConnectStateText":"Nicht verbunden. Hier klicken für Anwahl!",
         "HasActualData":{
            "StationId":3,
            "DpId":10,
            "Name":null,
            "Value":1,
            "TimeStamp":"\/Date(1405488343000)\/"
         },
         "Anlage":{
            "StationId":3,
            "DpId":20101,
            "Name":"Anlage",
            "Value":1,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "cmdSchalteAnlage":{
            "StationId":3,
            "DpId":20013,
            "Name":"cmdAnlage",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Kurzzeit":{
            "StationId":3,
            "DpId":20104,
            "Name":"Kurzzeit",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "cmdSchalteKurzzeit":{
            "StationId":3,
            "DpId":20012,
            "Name":"cmdKurzzeit",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Handbetrieb":{
            "StationId":3,
            "DpId":20160,
            "Name":"Handbetrieb",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Betriebsbereit":{
            "StationId":3,
            "DpId":20121,
            "Name":"Betriebsbereit",
            "Value":1,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Heizt":{
            "StationId":3,
            "DpId":20451,
            "Name":"Heizt",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "Sammelstoerung":{
            "StationId":3,
            "DpId":20140,
            "Name":"Sammelstoerung",
            "Value":1,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "SammelstoerungTechnisch":{
            "StationId":3,
            "DpId":20129,
            "Name":"SammelstoerungTechnisch",
            "Value":1,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "KommunikationsStoerung":{
            "StationId":3,
            "DpId":20138,
            "Name":"KommunikationsStoerung",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "KommunikationsStoerungKE":{
            "StationId":3,
            "DpId":20137,
            "Name":"KommunikationsStoerungKE",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/"
         },
         "AllowCommands":true,
         "AllowParameters":true
      }
   ]
}

1 个答案:

答案 0 :(得分:2)

我已经使用OpenLayers做到了这一点,所以这个答案可能不是最好的,但它可能会让你深入了解如何采用标记的视图模型并将其“绑定”到地图上以便任何更改视图模型反映在地图上。对我而言,关键是编写一个呈现航路点的订户功能。

这是我的基本视图模型。我称它们为航点,但它们是OpenLayers.Geometry.Point对象,所以我愿意猜测它们与Leaflet标记类似。

G.WaypointsViewModel = function() {
    // The list of waypoints.
    this.waypoints = ko.observableArray([])
}

我建立了这样的订户;评论来自我的实际代码,所以我猜我们都遇到了同样的问题!

// We cannot bind the OpenLayers line that links these waypoints to the
// waypoint list, so we need a manual subscription to update the line.
this.waypoints.subscribe(function(new_waypoints) {

}

理想情况下,我会编写一些聪明的代码来解决视图模型中发生了哪些变化,并且只进行正确的更新,但为了简单起见,我的函数所做的第一件事是摆脱所有当前的航点:

this.waypoints.subscribe(function(new_waypoints) {
    // Don't continue with an empty array.
    if (new_waypoints.length == 0) return

    // Get rid of the current drawings.
    this.removeMarkers() 
    ...

在OpenLayers中,删除标记很容易;我只是在代表标记层的变量上调用destroyFeatures:

    this.marker_layer = new OpenLayers.Layer.Vector("Markers Layer", {
        style: G.default_line_style
    })

    this.removeMarkers = function() {
        marker_layer.destroyFeatures()
    }

然后我重新绘制所有标记:

    while (waypoint = this.waypoints()[i]) {
        marker = new OpenLayers.Feature.Vector(
            waypoint, {type: 'waypoint', index: i}
        )
        this.marker_layer.addFeatures(marker)

        // Next...
        i++
    }

现在这已全部设置,用户在应用程序中执行的任何导致航点更改的内容(例如删除航点,移动航点等)都意味着地图会由KO订户自动更新。

这个视图模型的完整代码(其他一些事情正在进行中)在这里:

http://simonlikesmaps.appspot.com/js/app/view_models/G.WaypointsViewModel.js

使用它的应用程序在这里:

http://simonlikesmaps.appspot.com/

希望通过Leaflet为您提供相同的灵感。


事实上,我一直想阅读Leaflet一段时间,所以我去阅读,并将上面的模式描绘成一个应该与Leaflet一起使用的ViewModel。警告 - 这是未经测试的 - 所以肯定会有一些错误!

MarkersVM = function() {

    // Create leaflet map
    this.map = L.map('map').setView([51.505, -0.09], 13);

    // Add a marker layer
    this.addMarkerLayer();

    // Turn your JSON into an array of station, each with a lat/lon
    this.markers = ko.observableArray([
        {
            "StationId":1,
            "DpId":20101,
            "Name":"Anlage",
            "Value":1,
            "TimeStamp":"\/Date(-62135596800000)\/",
            "lat": "51",
            "lon": "0"
         },
         {
            "StationId":1,
            "DpId":20013,
            "Name":"cmdAnlage",
            "Value":0,
            "TimeStamp":"\/Date(-62135596800000)\/",
            "lat": "52",
            "lon": "1"
         },
    ]);

    // Subscribe to the array, to redraw the map.
    this.markers.subscribe(function(new_markers) {
        // Don't bother with an empty array
        if (new_markers.length == 0) return;

        // Start be removing all current markers; to do this, remove the marker layer.
        map.removeLayer(this.markers);

        // Add a fresh marker layer.
        this.addMarkerLayer();

        // Now add the points.
        var i = 0, marker;
        while (station = this.markers()[i]) {
            var marker = L.marker(station.lat, station.lon)

            // You can manipulate the marker here, eg add the name, the text, etc

            this.markers.add(marker);
        }
    }, this);

    this.addMarkerLayer = function() {
        this.markers = new L.FeatureGroup();
        map.addLayer(this.markers);
    }
}

这样,对JSON所做的任何更改都将更改视图模型中的markers数组,通过订阅函数将销毁地图上的标记,然后绘制新标记,确保新信息自动显示在地图中。