0

AngularJS サービスと Angular-Google-Maps を使用するアプリケーションがあり、マップ上に複数のマーカーを取得できますが、各マーカーをクリックしても機能しません。クリックを許可する唯一のマーカーは、ウィンドウを開いた後に閉じることができない最後のマーカーです。または、アドレスが1つしかない場合、マーカーは期待どおりに機能します。私は近くにいると思いますが、マーカーのクリックがすべてのマーカーで機能するために何が欠けているのかわかりません。私が見逃していること、または別の方法で行う必要があることについてのアイデアはありますか?

これが私のページのマークアップです。

<div ng-app="myMapApp" ng-controller="mapController">    
<ui-gmap-google-map center='map.center' zoom='map.zoom' options="options">        
    <ui-gmap-markers models="directoryMarkers" coords="'self'" icon="'icon'" click="'onClick'">
        <ui-gmap-windows show="show">
            <div ng-non-bindable>{{organization}}</div>
        </ui-gmap-window> 
    </ui-gmap-markers>
</ui-gmap-google-map>
</div>

myMapApp.js のコード

var app = angular.module("myMapApp", ['uiGmapgoogle-maps', 'ngStorage']);

mapController.js のコード

app.controller('mapController', function ($scope, Geocoder) {

$scope.map = { center: { latitude: 45, longitude: -73 }, zoom: 10 };

var hfValue = $("#ucDirectory_UcResults_hfResults");

$scope.directoryMarkers = [];

var createMarker = function (organization, address, latitude, longitude, i) {

    var ret = {
        latitude: latitude,
        longitude: longitude,
        address: address,
        organization: organization,
        show: false
    };

    ret.onClick = function () {
        console.log("Clicked!");
        ret.show = !ret.show;
    };

    ret["id"] = i;
    return ret;
};

var json = jQuery.parseJSON(hfValue[0].value);

var markers = [];
var i = 0;

var org;

for (var key in json) {
    if (json.hasOwnProperty(key)) {

        org = json[key].organization;



        if (json[key].address.length > 0) {

            Geocoder.geocodeAddress(json[key].address).then(function (data) {

            markers.push(createMarker(org, json[key].address, data.lat, data.lng, i))

            $scope.map.center.latitude = data.lat;
            $scope.map.center.longitude = data.lng;

            });

            i++;
        }
    }
}

$scope.directoryMarkers = markers;


});

geocoder-service.js のコード

 * An AngularJS Service for intelligently geocoding addresses using Google's API. Makes use of
 * localStorage (via the ngStorage package) to avoid unnecessary trips to the server. Queries
 * Google's API synchronously to avoid `google.maps.GeocoderStatus.OVER_QUERY_LIMIT`.
 *
 * @author: benmj
 * @author: amir.valiani
 *
 * Original source: https://gist.github.com/benmj/6380466
 */

/*global angular: true, google: true, _ : true */

'use strict';

//angular.module('geocoder', ['ngStorage']).factory('Geocoder', function ($localStorage, $q, $timeout, $rootScope) {
app.factory('Geocoder', function ($localStorage, $q, $timeout, $rootScope) {
    var locations = $localStorage.locations ? JSON.parse($localStorage.locations) : {};

    var queue = [];

    // Amount of time (in milliseconds) to pause between each trip to the
    // Geocoding API, which places limits on frequency.
    var QUERY_PAUSE = 250;

    /**
     * executeNext() - execute the next function in the queue.
     *                  If a result is returned, fulfill the promise.
     *                  If we get an error, reject the promise (with message).
     *                  If we receive OVER_QUERY_LIMIT, increase interval and try again.
     */
    var executeNext = function () {
        var task = queue[0],
          geocoder = new google.maps.Geocoder();

        geocoder.geocode({ address: task.address }, function (result, status) {

            if (status === google.maps.GeocoderStatus.OK) {

                var parsedResult = {
                    lat: result[0].geometry.location.lat(),
                    lng: result[0].geometry.location.lng(),
                    formattedAddress: result[0].formatted_address
                };
                locations[task.address] = parsedResult;

                $localStorage.locations = JSON.stringify(locations);

                queue.shift();
                task.d.resolve(parsedResult);

            } else if (status === google.maps.GeocoderStatus.ZERO_RESULTS) {
                queue.shift();
                task.d.reject({
                    type: 'zero',
                    message: 'Zero results for geocoding address ' + task.address
                });
            } else if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
                if (task.executedAfterPause) {
                    queue.shift();
                    task.d.reject({
                        type: 'busy',
                        message: 'Geocoding server is busy can not process address ' + task.address
                    });
                }
            } else if (status === google.maps.GeocoderStatus.REQUEST_DENIED) {
                queue.shift();
                task.d.reject({
                    type: 'denied',
                    message: 'Request denied for geocoding address ' + task.address
                });
            } else {
                queue.shift();
                task.d.reject({
                    type: 'invalid',
                    message: 'Invalid request for geocoding: status=' + status + ', address=' + task.address
                });
            }

            if (queue.length) {
                if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
                    var nextTask = queue[0];
                    nextTask.executedAfterPause = true;
                    $timeout(executeNext, QUERY_PAUSE);
                } else {
                    $timeout(executeNext, 0);
                }
            }

            if (!$rootScope.$$phase) { $rootScope.$apply(); }
        });
    };

    return {
        geocodeAddress: function (address) {
            var d = $q.defer();

            if (_.has(locations, address)) {
                d.resolve(locations[address]);
            } else {
                queue.push({
                    address: address,
                    d: d
                });

                if (queue.length === 1) {
                    executeNext();
                }
            }

            return d.promise;
        }
    };
});
4

1 に答える 1

2

余談ですが、同時に多くのウィンドウを開いていない場合は、windows ディレクティブを使用しないでください。代わりに、window ディレクティブを使用して、マーカーの兄弟として定義してください。ドキュメントで推奨されているとおりです。

しかし、元の質問に答えるために、このplnkrは、ジオコーディングを除いたコードを使用して、ウィンドウ付きのマーカーを生成します。クリックは値が変更される前に発生するため、マーカーを目的の場所に移動するには、マーカーを 2 回クリックする必要があります。

必要な動作を取得するには、次のようになります。

html:

<ui-gmap-google-map center='map.center' zoom='map.zoom' options="options">        
<ui-gmap-markers fit="true" models="directoryMarkers" coords="'self'" icon="'icon'" click="'onClick'">
</ui-gmap-markers>
<ui-gmap-window show="selected.show" coords="selected">
        <div>{{selected.organization}}</div>
</ui-gmap-window> 

コントローラ:

  $scope.map = {
    center: {
      latitude: 45,
      longitude: -73
    },
    zoom: 10
  };

  $scope.directoryMarkers = [];
  $scope.selected = null;

  var createMarker = function(latitude, longitude, i) {

    var ret = {
      latitude: latitude,
      longitude: longitude,
      organization: "Foo",
      show: false
    };

    ret.onClick = function() {
      console.log("Clicked!");
      $scope.selected = ret;
      ret.show = !ret.show;
    };

    ret["id"] = i;
    return ret;
  };

  var markers = [];

  var org;

  var coords = chance.coordinates().split(",");
  $scope.map.center.latitude = coords[0];
  $scope.map.center.longitude = coords[1];
  for (var i = 0; i < 20; i++) {
    coords = chance.coordinates().split(",");
    markers.push(createMarker(coords[0], coords[1], i));
  }

  $scope.directoryMarkers = markers;

このplnkrで一緒に見ることができます: http://plnkr.co/edit/rT4EufIGcjplgd8orVWu?p=preview

于 2014-12-17T17:23:48.867 に答える