gabesmed / ember-leaflet

Ember + Leaflet = Fun with maps
gabesmed.github.io/ember-leaflet
MIT License
164 stars 35 forks source link

Manage Tile Layers #75

Closed miguelcobain closed 10 years ago

miguelcobain commented 10 years ago

Is it possible to bind MapView child layers to a controller?

I'm trying to change TileLayers based on a controller's array.

This is probably related with #35, but I'm trying to have the MapView bound to an array on the controller instead of having to call pushObject on the MapView.

gabesmed commented 10 years ago

Interesting. I wonder if this would be possible?

App.TileLayersController = Ember.ArrayController.extend({
  content: [
    {tileUrl: '...'},
    {tileUrl: '...'},
    {tileUrl: '...'}]
});
App.TileLayer = EmberLeaflet.TileLayer.extend({
  tileUrl: Ember.computed.alias('content.tileUrl')
});
App.TileLayersLayer = EmberLeaflet.CollectionLayer.extend({
  itemLayerClass: App.TileLayer
});
App.TileLayersView = EmberLeaflet.MapView.extend({
  childLayers: [App.TileLayersLayer]
});
miguelcobain commented 10 years ago

Thanks, but something seems missing to me.

Where are you binding to the controller?

miguelcobain commented 10 years ago

@gabesmed you are god. Your suggestions helped a lot!

var TileLayer = EmberLeaflet.TileLayer.extend({
  tileUrl: Ember.computed.alias('content.tileUrl'),
  options: Ember.computed.alias('content.options')
});

var TileLayersLayer = EmberLeaflet.CollectionLayer.extend({
  itemLayerClass: TileLayer,
  contentBinding: 'controller.tiles'
});

export default EmberLeaflet.MapView.extend({
  childLayers:[TileLayersLayer]
});

and my controller:

export default Ember.ArrayController.extend({
  tiles:function(){
    return this.tileLayers.filterBy('enabled').mapBy('layer');
  }.property('tileLayers.@each.enabled'),
  tileLayers:[
    {
      id: 'osm',
      name: 'OpenStreetMap',
      enabled: true,
      layer: {
        tileUrl:'http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png',
        options:{
          attribution: '&copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
          maxZoom:20,
          maxNativeZoom:18
        }
      }
    },{
      id: 'stamen',
      name: 'Stamen',
      layer: {
        tileUrl:'http://{s}.tile.stamen.com/{styleName}/{z}/{x}/{y}.png',
        options:{
          styleName:'toner-lite',
          attribution:'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://cloudmade.com">CloudMade</a>',
          maxZoom:20,
          maxNativeZoom:18
        }
      }
    },{
      id: 'esri',
      name: 'Esri WorldImagery',
      layer: {
        tileUrl:'http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
        options:{
          attribution: 'Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community',
          maxZoom:20,
          maxNativeZoom:18
        }
      }
    }
  ]
});

Now if I want to include a layer in the map I just need to toggle enabled to true! Then the filter applies. Lessons learnt:

  1. The trick here were the Collection Layers. Very powerful.
  2. Also, it took me a while to understand that child views share their parent view controller.

Anything to add?

Thanks a lot.

gabesmed commented 10 years ago

oh yeah you're totally right, you need to explicitly bind TileLayersLayer.content to the controller, like you just did