【问题标题】:How to use knockout.js with leaflet.js map markers?如何使用带有leaflet.js 地图标记的knockout.js?
【发布时间】:2023-03-05 16:07:01
【问题描述】:

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

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

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

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

确切地说:我可以为每个植物添加(静态)标记,这不是问题,但我不能将它们数据绑定到视图模型以动态表示视图模型中的变化值。有没有办法做到这一点?

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

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

【问题讨论】:

  • 标记存在哪些值?是否只有状态发生了变化,而您希望颜色发生变化?
  • 由于您似乎无法真正使用标记,因此您需要使用 js 插入/更新标记。您仍然可以使用subscribe 函数来获取视图模型的更新并将它们传递给标记。
  • 这将是一个好的开始,但最后还有更多:显示值的文本和显示植物名称的文本。
  • 你可以考虑写一个 custom binding 来绘制你的标记。
  • 能否请您为每个标记提供一些 json。这将有助于回答这个问题。

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


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-14
    • 1970-01-01
    • 2013-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多