javascript - 如何将 knockout.js 与 leaflet.js map 标记一起使用?

标签 javascript asp.net-mvc html knockout.js leaflet

我们正在为位于不同位置的工业工厂构建网络可视化。目前,我们的概览页面使用表格布局。每行代表一种植物及其最重要的状态和值(value)。

现在需要交替显示带有标记的 map 。每个标记的颜色应代表当前状态(绿色=正常、红色=错误、黄色=警告等)。

在我们当前基于表格的页面中,我们使用 knockout.js 将 View 模型中的各个植物属性绑定(bind)到表格行(以及其中相应的 div 等)。每当状态或值发生变化时, View 模型的值都会通过信号器更新,因此您可以将其视为植物状态的基于事件的实时表示。

由于此 View 模型已包含我们需要在 map 上显示的所有信息,我想将传单标记绑定(bind)到 View 模型,但我看不出如何做到这一点。问题是没有可以与 data-bind 属性一起使用的标记元素。

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

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

更新:这是我的 View 模型的实际 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
      }
   ]
}

最佳答案

我已经用 OpenLayers 做到了这一点,所以这个答案可能不是最好的,但它可能会让您深入了解如何获取标记的 View 模型并将其“绑定(bind)”到 map ,以便任何更改 View 模型反射(reflect)在 map 上。对我来说,关键是编写一个呈现航路点的订阅者函数。

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

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

我像这样建立一个订阅者;评论来 self 的实际代码,所以我想我们都遇到了同样的问题!

// 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) {

}

理想情况下,我会编写一些聪明的代码来计算出 View 模型中发生的变化,然后进行正确的更新,但为了简单起见,我的函数所做的第一件事就是删除所有当前的路标:

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 订阅者会自动更新 map 。

这个 View 模型的完整代码(还有一些其他事情正在发生)在这里:

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 所做的任何更改都会更改 View 模型中的标记数组,通过订阅函数将破坏 map 上的标记,然后绘制新标记,确保新信息自动显示在 map 中。

关于javascript - 如何将 knockout.js 与 leaflet.js map 标记一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24773771/

相关文章:

javascript - 如何使用 jQuery 遍历嵌套的 HTML div 元素

javascript - 在javascript中向原型(prototype)和对象文字添加函数之间的区别

javascript - 如何在 Angularjs 中点击 div 标签时使用 ui-sref?

asp.net-mvc - 如何停止 MVC 中的多条路由匹配?

jquery - ASP.NET MVC 中的条纹表行(不使用 jQuery 或等效项)

html - 填充 float 元素

javascript - 将鼠标悬停在图表上的某个点上时显示所有图表的工具提示

javascript - 选项卡内容无法正确呈现

javascript - JQuery .load() 没有添加到 DOM?

asp.net - 重定向不适用于移动 View asp.net