Coffeescript类不符合预期

时间:2014-08-17 16:55:51

标签: javascript coffeescript openlayers

错误的标题名称,抱歉。不确定如何总结这一点。

我尝试使用OpenLayers地图API将带有多个标记的地图打印到页面。我有工作代码,但是当我尝试将它移动到一个单独的Coffeescript类时,它会无声地失败。以下代码有效:

fromProjection = new OpenLayers.Projection("EPSG:4326") # Transform from WGS 1984
toProjection = new OpenLayers.Projection("EPSG:900913") # to Spherical Mercator Projection
mapnik = new OpenLayers.Layer.OSM()
markers = new OpenLayers.Layer.Markers("Markers")

map = new OpenLayers.Map("john-muir-trail-map")
markerCoordinates = -> $("\#john-muir-trail-data").data('markers').split('+')

paint = ->
  map.addLayer(mapnik)
  map.addLayer(markers)

  for pair in markerCoordinates()
    coords = pair.split(":")
    pos = new OpenLayers.LonLat(coords[1], coords[0]).transform( fromProjection, toProjection )
    markers.addMarker(new OpenLayers.Marker(pos))
    map.setCenter(pos, 8)


paint()

它依赖于两个存在的div(一个具有id' john-muir-trail-map'另一个具有id' john-muir-trail-data'以及一些标记数据)。当上面的代码在我的主.coffee文件中时,它的效果非常好。

但是,当我尝试通过将地图代码移动到单独的OpenLayerMap Coffeescript类来模块化时,没有错误提升,但它只是不起作用。这就是我所做的。 (我非常确定我正确地包含了这些内容。该类可以从我的主文件中获取,其方法和属性也是如此):

class OpenLayersMap

  constructor: (mapId) ->
    @mapId = mapId

  fromProjection: new OpenLayers.Projection("EPSG:4326") # Transform from WGS 1984
  toProjection: new OpenLayers.Projection("EPSG:900913") # to Spherical Mercator Projection
  mapnik: new OpenLayers.Layer.OSM()
  markers: new OpenLayers.Layer.Markers("Markers")

  map: new OpenLayers.Map("#{@mapId}-map")
  markerCoordinates: -> $("\##{@mapId}-data").data('markers').split('+')

  paint: ->
    @map.addLayer(@mapnik)
    @map.addLayer(@markers)

    for pair in @markerCoordinates()
      coords = pair.split(":")
      pos = new OpenLayers.LonLat(coords[1], coords[0]).transform( @fromProjection, @toProjection )
      @markers.addMarker(new OpenLayers.Marker(pos))
      @map.setCenter(pos, 8)

window.OpenLayersMap = OpenLayersMap

然后我在之前的文件中调用它,如下所示:

map = new OpenLayersMap('john-muir-trail')
map.paint()

我不认为OpenLayers关于预测等的详细信息是相关的。重要的是mapId正在传入并正确使用,如果我在paint()函数中抛出一个调试器,调试器就会被命中,那时所有可用的属性对我来说都很好。正确包含了该类,等等。但是,没有绘制地图。

我有Ruby背景,我觉得我对paint()函数的效果和副作用感到困惑。如果它的行为基本相同,为什么它会在不同的文件中表现不同?

为什么会失败(默默地)的任何想法?它让我有点疯狂。

2 个答案:

答案 0 :(得分:2)

我相信您在地图属性中使用@会导致问题。您没有访问OpenLayersMap的当前实例,而是在mapId上调用静态属性OpenLayersMap。例如:

map: new OpenLayers.Map("#{@mapId}-map")

将编译成:

OpenLayersMap.prototype.map = new OpenLayers.Map("" + OpenLayersMap.mapId + "-map");

您需要使map方法访问构造函数中设置的@mapId

map: -> new OpenLayers.Map("#{@mapId}-map")

答案 1 :(得分:2)

我完全同意Kyle Needham's explanation,但我想提出另一种解决方案。

要修复代码,只需将map赋值从类原型移动到其构造函数:

class OpenLayersMap
  constructor: (mapId) ->
    @mapId = mapId
    @map = new OpenLayers.Map("#{@mapId}-map")

您应该考虑将fromProjectiontoProjectionmapnikmarkers定义移动到构造函数中。

在您当前的实现中,OpenLayersMap的所有实例都具有相同的markers值,例如:

l1 = new OpenLayersMap 'l1'
l2 = new OpenLayersMap 'l2'
l1.markers is l2.markers # true, meaning they are the same object

因此,通过变异l1.markers,您不仅会影响OpenLayersMap类的所有现有实例,还会更改其原型。

这意味着通过在OpenLayersMap类的任何实例中改变这四个属性中的任何一个,您将对所有其他实例进行相同的更改。

如果所有这些类(ProjectionLayerMarkers)都是不可变的(即提供一堆帮助程序,但不保持状态)那么你的实现是正确的,但是我怀疑是否有人会打扰自己将一群无国籍的助手包括在课堂上。

因此,请考虑将您的代码更改为:

class OpenLayersMap
  constructor: (mapId) ->
    @mapId = mapId
    @map = new OpenLayers.Map "#{@mapId}-map"
    @fromProjection = new OpenLayers.Projection "EPSG:4326"
    @toProjection = new OpenLayers.Projection "EPSG:900913"
    @mapnik = new OpenLayers.Layer.OSM()
    @markers = new OpenLayers.Layer.Markers "Markers"

在这种情况下,OpenLayersMap的每个实例都有自己的fromProjectiontoProjectionmapnikmarkers