Pregunta

Tengo un módulo que he creado para Google Maps v3 que estoy tratando de convertir en una vista constructor Backbone.js.

Aquí está mi punto de vista en lo que va del módulo: Voy a explicar los problemas que tengo después del código:

pg.views.CreateMap = Backbone.View.extend({

  tagName:  "div",
  className: "map",

  events: {},

  latitude:   "-23.56432",
  longitude:  "-46.65183", 

  initialize: function() {
    _.bindAll(this, 'render', 'dragMarker', 'dragMap');

    this.latlng = new google.maps.LatLng(this.latitude, this.longitude);
    var myOptions = {
      zoom: 16,
      center: this.latlng,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    this.map = new google.maps.Map($(this.el)[0], myOptions);
    this.marker = new google.maps.Marker({
      map: this.map,
      position: this.latlng, 
      draggable: true
    });

    google.maps.event.addListener(this.marker, "dragend", this.dragMarker());

    google.maps.event.addListener(this.map, "dragend", this.dragMap());

  },

  render: function() {
    return this;
  },

  dragMarker: function() {
    this.latlng = this.marker.getPosition();
    this.map.panTo(this.latlng);
  },

  dragMap: function() {
    this.latlng = this.map.getCenter();
    this.marker.setPosition(this.latlng);
  }

});

El problema que estoy teniendo es con los detectores de eventos mapas de Google y cómo "este" se maneja.

Que originalmente no tenía los métodos dragMarker y dragMap y en lugar de estos dos en el bloque de inicialización:

google.maps.event.addListener(this.marker, "dragend", function() {
  this.latlng = this.marker.getPosition();
  this.map.panTo(this.latlng);
});

google.maps.event.addListener(this.map, "dragend", function() {
  this.latlng = this.map.getCenter();
  this.marker.setPosition(this.latlng);
});

El problema que encontré con este primer enfoque es que "este" dentro de esas funciones anónimas se refirió a "this.marker" y "this.map", respectivamente. El problema de este primer enfoque fue que en la primera escucha, no tenía forma de referirse a "this.map" y por lo tanto no se pudo realizar una panTo (). Con el segundo oyente, no tenía manera de referirse a "this.marker" y por lo tanto no podía centrar el mapa en torno a ese marcador usando setPosition ().

I entonces pensó que podía sacar las funciones anónimas en los oyentes y declarar como métodos de la vista, que yo a continuación, realizar una _.bindAll (esto "dragMarker", "dragMap");

El problema con este enfoque es que entonces yo tenía que escribir los oyentes en el bloque de eventos, así:

google.maps.event.addListener(this.marker, "dragend", this.dragMarker());

google.maps.event.addListener(this.map, "dragend", this.dragMap());

Esto significó que cuando me llamó el constructor con newmap = new pg.views.CreateMap; que el "this.dragMarker ()" y "this.dragMap ()" se evaluaron inmediatamente en vez de ser evaluado como una devolución de llamada cuando se activa el evento "dragend".

No hay problema pensé y luego se envuelve los alzados en funciones anónimas, así:

google.maps.event.addListener(this.marker, "dragend", function() {
  this.dragMarker();
});

google.maps.event.addListener(this.map, "dragend", function() {
  this.dragMap();
});

Desafortunadamente esto también me lleva de vuelta a un problema anterior que el "presente" en "this.dragMarker" ya no se refiere al objeto padre construí, pero en su lugar se refieren a "this.marker" de nuevo. El mismo problema se produce con el segundo oyente.

estoy completamente atascado aquí. Alguien tiene alguna idea sobre cómo puedo solucionar esto?

¿Fue útil?

Solución

Tome las funciones anónimas denominadas en dragend y se unen de forma explícita.

_.bindAll(this, 'dragMarker', 'dragMap');
google.maps.event.addListener(this.marker, "dragend", this.dragMarker);
/* etc ... */

Esta this manera siempre estará ligada a CreateMap incluso si llama fuera de contexto.

Otros consejos

Me solucionó este problema mediante el uso de la que / auto común truco en Javascript.

var self = this;

google.maps.event.addListener(this.marker, "dragend", function() {
  self.latlng = this.getPosition();
  self.map.panTo(self.latlng);
});

google.maps.event.addListener(this.map, "dragend", function() {
  self.latlng = this.getCenter();
  self.marker.setPosition(self.latlng);
});

Si alguien tiene una solución que no requiere este truco, soy todo oídos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top