huafu / ember-google-map

An Ember addon to include a google-map Ember friendly component in your apps.
http://huafu.github.io/#/ember?name=ember-google-map
MIT License
87 stars 34 forks source link

Adding objects not supported by plugin #66

Open billybonks opened 9 years ago

billybonks commented 9 years ago

I needed to use the drawing manager, so i created one using your framework

import Ember from 'ember';

import helpers from 'ember-google-map/core/helpers';
import GoogleObjectMixin from 'ember-google-map/mixins/google-object';

var computed = Ember.computed;
var alias = computed.alias;
var fmt = Ember.String.fmt;
var on = Ember.on;
/**
 * @class GoogleMapCircleView
 * @extends GoogleMapCoreView
 */
export default Ember.Object.extend(GoogleObjectMixin, {
  googleFQCN: 'google.maps.drawing.DrawingManager',

  googleProperties:{
    drawingMode:{name:'drawingMode'},
    drawingControl:{name:'drawingControl',optionOnly:true},
    drawingControlOptions:{name:'drawingControlOptions',optionOnly:true},
    map:         {readOnly: true},
  },

  _coreGoogleEvents:      ['circlecomplete','markercomplete','polygoncomplete','polylinecomplete','rectanglecomplete'],

  drawingMode: google.maps.drawing.OverlayType.MARKER,
  drawingControl: true,
  drawingControlOptions: {
    position: google.maps.ControlPosition.TOP_CENTER,
    drawingModes: [
      google.maps.drawing.OverlayType.MARKER,
      google.maps.drawing.OverlayType.POLYGON,
      google.maps.drawing.OverlayType.POLYLINE,
      google.maps.drawing.OverlayType.CIRCLE
    ]
  },

  initGoogleObject: on('init', function () {
    // force the creation of the object
    if (helpers.hasGoogleLib() && !this.get('googleObject')) {
      this.createGoogleObject();
    }
  }),

  destroyGoogleObject: on('destroy', function () {
    var object = this.get('googleObject');
    if (object) {
      // detach from the map
      object.setMap(null);
      this.set('googleObject', null);
    }
  }),

  initGoogleMap: on('didInsertElement', function () {
    debugger;
  })
});

but to initialise and connect the object, i needed to add this to my controller, which isn't ideal

DrawingManager.create({googleEventsTarget:view.get('targetObject'),map:view.get('map'),                                      ev_markercomplete:'markerAdded',ev_polygoncomplete:'polygonAdded'});

do you have a recommendation to adding unsupported objects to the map ? i will be doing something similar for custom overlays

DanLeininger commented 9 years ago

Any luck with this @billybonks? I too am trying to add custom overlays.

billybonks commented 9 years ago

you basically need, to access the map object from the component, to pass to your custom overlay here is an example

import helpers from 'ember-google-map/core/helpers';
import GoogleObjectMixin from 'ember-google-map/mixins/google-object';
import Ember from 'ember';

var on = Ember.on;

export default Ember.Object.extend(GoogleObjectMixin, {
  googleFQCN: 'ResizableImageOverlay',

  googleProperties:{
    bounds:{name:'bounds',optionOnly:true},
    image:{name:'image',optionOnly:true},
    map:         {readOnly: true},
    center:      {readOnly: true},
    opacity:     {readOnly: true}
  },

  _coreGoogleEvents:      [],

  initGoogleObject: on('init', function () {
    // force the creation of the object
    if (helpers.hasGoogleLib() && !this.get('googleObject')) {
      this.createGoogleObject();
    }
  }),

  destroyGoogleObject: on('destroy', function () {
    var object = this.get('googleObject');
    if (object) {
      // detach from the map
      object.setMap(null);
      this.set('googleObject', null);
    }
  })
});

ResizableImageOverlay.prototype = new google.maps.OverlayView();

var STATES = {
  MOVE:1,
  N:2,
  S:3,
  E:4,
  NE:5,
  SW:6,
  NW:7,
  SE:8,
  W:9,
};

ResizableImageOverlay.prototype.buttons=[
  {name:'circle bottom-left',state:STATES.SW},
  {name:'circle bottom-right',state:STATES.SE},
  {name:'circle top-right',state:STATES.NE},
  {name:'circle top-left',state:STATES.NW},
  {name:'circle top-middle',state:STATES.N},
  {name:'circle bottom-middle',state:STATES.S},
  {name:'circle right-middle',state:STATES.E},
  {name:'circle left-middle',state:STATES.W}
];

ResizableImageOverlay.prototype.eventTargets = {};

function ResizableImageOverlay(options) {
  Ember.merge(this,options);
  // Define a property to hold the image's div. We'll
  // actually create this div upon receipt of the onAdd()
  // method so we'll leave it null for now.
  this.div_ = null;

  // Explicitly call setMap on this overlay.
  this.setMap(options.map);
}

/**
 * onAdd is called when the map's panes are ready and the overlay has been
 * added to the map.
 */

ResizableImageOverlay.prototype.onAdd = function() {
  var self = this;
  var map = this.map;
  var div = this.addDom();
  this.bindListeners();

  var lat = this.center.A;
  var lang = this.center.F;

  var swBound = new google.maps.LatLng(lat-2, lang-2);
  var neBound = new google.maps.LatLng(lat+2, lang+2);

  this.bounds = new google.maps.LatLngBounds(swBound, neBound);
  console.log(this.bounds);
  google.maps.event.addDomListener( div, 'mousedown', function(event){
      map.setOptions({draggable: false});
      self.propergateEvent(event);
  });

  google.maps.event.addDomListener(div, 'mouseup', function(event){
      map.setOptions({draggable: true});
      self.propergateEvent(event);
  });

  google.maps.event.addListener(map,'mousemove',function(event){
    var latLng = event.latLng;
    var ne = self.bounds.getNorthEast();
    var sw = self.bounds.getSouthWest();

    if(self.state){
      switch(self.state) {
        case STATES.NE:
          ne = latLng;
          break;
        case STATES.SW:
          sw = latLng;
          break;
        case STATES.NW:
          ne =  new google.maps.LatLng(latLng.lat(),ne.lng());
          sw = new google.maps.LatLng(sw.lat(),latLng.lng());
          break;
        case STATES.SE:
          ne =  new google.maps.LatLng(ne.lat(),latLng.lng());
          sw = new google.maps.LatLng(latLng.lat(),sw.lng());
          break;
        case STATES.N:
          ne =  new google.maps.LatLng(latLng.lat(),ne.lng());
          break;
        case STATES.S:
          sw = new google.maps.LatLng(latLng.lat(),sw.lng());
          break;
        case STATES.W:
          sw =  new google.maps.LatLng(sw.lat(),latLng.lng());
          break;
        case STATES.E:
          ne = new google.maps.LatLng(ne.lat(),latLng.lng());
          break;
        case STATES.MOVE:
          var center = self.bounds.getCenter();
          var diffLat =   center.lat() - latLng.lat();
          var diffLan =    center.lng() - latLng.lng();
          ne = new google.maps.LatLng(ne.lat()-diffLat,ne.lng()-diffLan);
          sw = new google.maps.LatLng(sw.lat()-diffLat,sw.lng()-diffLan);
          break;
      }
      self.bounds = new google.maps.LatLngBounds(sw,ne);
      self.draw();
    }
  });

};

ResizableImageOverlay.prototype.addDom = function() {
  var div = document.createElement('div');
  var img = document.createElement('img');
  var $div = $(div);
  var $img = $(img);
  var imageClass = 'resizable-image';
  $img.addClass(imageClass);
  $img.css({
    width:"100%",
    height:"100%",
    opacity:this.opacity
    //position:"absolute"
  });
  $img.attr('src',this.image);
  $div.append($img);
  this.eventTargets[imageClass] = {object:$img[0],state:STATES.MOVE};
  $div.addClass('imageWrapper');
  for(var i = 0; i<this.buttons.length;i++){
    var name = this.buttons[i].name;
    var $circle = $(document.createElement('div')).addClass(name);
    this.eventTargets[name] = {object:$circle[0],state:this.buttons[i].state};
    $div.prepend($circle);
  }
  this.div_ = div;
  var panes = this.getPanes();
  panes.overlayMouseTarget.appendChild(div);
  return div;
};

ResizableImageOverlay.prototype.draw = function() {

  // We use the south-west and north-east
  // coordinates of the overlay to peg it to the correct position and size.
  // To do this, we need to retrieve the projection from the overlay.
  var overlayProjection = this.getProjection();

  // Retrieve the south-west and north-east coordinates of this overlay
  // in LatLngs and convert them to pixel coordinates.
  // We'll use these coordinates to resize the div.
  var sw = overlayProjection.fromLatLngToDivPixel(this.bounds.getSouthWest());
  var ne = overlayProjection.fromLatLngToDivPixel(this.bounds.getNorthEast());

  // Resize the image's div to fit the indicated dimensions.
  var div = this.div_;
  div.style.left = sw.x + 'px';
  div.style.top = ne.y + 'px';
  div.style.width = (ne.x - sw.x) + 'px';
  div.style.height = (sw.y - ne.y) + 'px';
};

ResizableImageOverlay.prototype.onRemove = function() {
  this.div_.parentNode.removeChild(this.div_);
  this.div_ = null;
};

ResizableImageOverlay.prototype.propergateEvent = function(event){
  var targetName = event.srcElement.className;
  var type = event.type;
  var object = this.eventTargets[targetName].object;
  google.maps.event.trigger(object,type,event,this.eventTargets[targetName].state);
};

ResizableImageOverlay.prototype.bindListeners = function() {
  var self = this;
  for(var key in this.eventTargets){
    var object = this.eventTargets[key].object;
    google.maps.event.addListener(object, 'mousedown', function(event,state){
      self.state = state;
      self.EventLatLang = self.getProjection().fromContainerPixelToLatLng(new google.maps.Point(event.x, event.y));
    });

    google.maps.event.addListener(object, 'mouseup', function(event,state){
      self.state = null;
    });
  }
};

window.ResizableImageOverlay = ResizableImageOverlay;